S es un programa de servidor: digamos que es un servidor HTTP, por lo que utilizará el número de puerto conocido para HTTP , que es 80. Lo ejecuto en un host con dirección IP 10.0.0.4, por lo que escuchará las conexiones 10.0.0.4:80(porque ahí es donde todos esperarán encontrarlo).
Dentro de S , voy a crear un socket y vincularlo a esa dirección: ahora, el sistema operativo sabe que las conexiones que entran 10.0.0.4:80deben enrutarse a mi proceso S a través de ese socket en particular.
salida de netstat una vez que el socket está vinculado:
$ netstat --tcp -lan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
NÓTESE BIEN. la dirección local es todo ceros, porque S no le importa cómo sus clientes lleguen a él
Una vez que S tiene este socket enlazado, aceptará conexiones: cada vez que un nuevo cliente se conecta, acceptdevuelve un nuevo socket, que es específico para ese cliente
Salida de netstat una vez que se acepta una conexión:
$ netstat --tcp -lan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 10.0.0.4:80 10.0.0.5:55715 ESTABLISHED
10.0.0.4:80representa el final de la conexión de S y está asociado con el socket devuelto poraccept
10.0.0.5:55715es el final de la conexión del cliente y está asociado con el socket que el cliente pasó para conectarse . El puerto del cliente no se utiliza para nada excepto para enrutar paquetes en esta conexión TCP al proceso correcto: el núcleo del cliente lo asigna aleatoriamente desde el rango de puertos efímeros.
Ahora, S puede continuar aceptando más conexiones de clientes ... cada uno tendrá su propio socket, cada socket estará asociado con una conexión TCP única y cada conexión tendrá una dirección remota única. S rastreará el estado del cliente (si hay alguno) al asociarlo con el socket.
Entonces, más o menos:
- la dirección IP es para el enrutamiento entre hosts en la red
- el puerto es para enrutar al socket correcto en el host
- Casi dije que el proceso era correcto , pero en realidad es posible tener múltiples procesos (generalmente secundarios), todos aceptando en el mismo socket ...
- sin embargo, cada vez que
acceptregresa una de las llamadas simultáneas , lo hace en un solo proceso, cada socket de conexión entrante es único para una instancia del servidor
- el socket es el objeto que utiliza un proceso para hablar con el sistema operativo acerca de una conexión particular, como un descriptor de archivo
- como se menciona en los comentarios, hay muchos otros usos para los sockets que no usan puertos en absoluto: por ejemplo, socketpair crea un par de sockets conectados que no tienen ningún esquema de direccionamiento, la única forma de usar esa tubería es el proceso que llamó
socketpair, ser hijo de ese proceso y heredar uno, o pasar explícitamente uno de los sockets de ese proceso