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:80
deben 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, accept
devuelve 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:80
representa el final de la conexión de S y está asociado con el socket devuelto poraccept
10.0.0.5:55715
es 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
accept
regresa 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