networking - informatica - tcp socket c++
¿Cómo funciona la función accept() de la API de socket? (4)
Como dijo el otro tipo, un socket está identificado de forma única por un 4-tuple (IP de cliente, puerto de cliente, IP de servidor, puerto de servidor).
El proceso del servidor que se ejecuta en el Servidor IP mantiene una base de datos (lo que significa que no me importa qué tipo de tabla / lista / árbol / matriz / estructura de datos mágicos utiliza) de sockets activos y escucha en el puerto del servidor. Cuando recibe un mensaje (a través de la pila TCP / IP del servidor), comprueba la dirección IP y el puerto del cliente contra la base de datos. Si la dirección IP del cliente y el puerto del cliente se encuentran en una entrada de la base de datos, el mensaje se transfiere a un manejador existente, de lo contrario se crea una nueva entrada de base de datos y se genera un nuevo manejador para manejar ese socket.
En los primeros días de ARPAnet, ciertos protocolos (FTP para uno) escuchaban un puerto específico para solicitudes de conexión y respondían con un puerto de transferencia. Otras comunicaciones para esa conexión pasarían por el puerto de transferencia. Esto se hizo para mejorar el rendimiento por paquete: las computadoras eran varios órdenes de magnitud más lentas en esos días.
El socket API es el estándar de facto para las comunicaciones TCP / IP y UDP / IP (es decir, el código de red tal como lo conocemos). Sin embargo, una de sus funciones principales, accept()
es un poco mágico.
Para tomar prestada una definición semi-formal:
accept () se usa en el servidor. Acepta un intento entrante recibido para crear una nueva conexión TCP desde el cliente remoto y crea un nuevo socket asociado con el par de direcciones de socket de esta conexión.
En otras palabras, accept
devuelve un nuevo socket a través del cual el servidor puede comunicarse con el cliente recién conectado. El socket anterior (en el que se llamó a accept
) permanece abierto, en el mismo puerto, escuchando nuevas conexiones.
¿Cómo funciona el trabajo? ¿Cómo se implementa? Hay mucha confusión sobre este tema. Muchas personas afirman aceptar abre un nuevo puerto y se comunica con el cliente a través de él. Pero obviamente esto no es cierto, ya que no se abre ningún puerto nuevo. En realidad, puede comunicarse a través del mismo puerto con diferentes clientes, pero ¿cómo? Cuando varios hilos llaman a recv
en el mismo puerto, ¿cómo saben los datos a dónde ir?
Supongo que es algo así como que la dirección del cliente está asociada con un descriptor de socket, y cada vez que los datos llegan a través de recv
se enrutan al socket correcto, pero no estoy seguro.
Sería genial obtener una explicación completa del funcionamiento interno de este mecanismo.
Lo que me confundió cuando estaba aprendiendo esto, fue que los términos socket
y port
sugieren que son algo físico, cuando de hecho son solo estructuras de datos que el núcleo usa para abstraer los detalles de la red.
Como tal, las estructuras de datos se implementan para poder mantener separadas las conexiones de diferentes clientes. En cuanto a cómo se implementan, la respuesta es a). No importa, el propósito de la API de sockets es precisamente que la implementación no debería importar o b) simplemente eche un vistazo. Además de los muy recomendados libros de Stevens que brindan una descripción detallada de una implementación, consulte la fuente en Linux o Solaris o en uno de los BSD.
Solo para agregar a la respuesta dada por el usuario "17 de 26"
El zócalo en realidad consiste en 5 tuplas - (fuente IP, puerto de origen, IP de destino, puerto de destino, protocolo). Aquí el protocolo podría ser TCP o UDP o cualquier protocolo de capa de transporte. Este protocolo se identifica en el paquete del campo ''protocolo'' en el datagrama IP.
Por lo tanto, es posible tener diferentes aplicaciones en el servidor que se comunican con el mismo cliente exactamente en las mismas 4 tuplas pero diferentes en el campo de protocolo. Por ejemplo
Apache en el lado del servidor hablando (server1.com:880-client1:1234 en TCP) y World of Warcraft hablando (server1.com:880-client1:1234 en UDP)
Tanto el cliente como el servidor manejarán esto como campo de protocolo en el paquete IP en ambos casos, es diferente incluso si los otros 4 campos son iguales.
Su confusión radica en pensar que un socket está identificado por IP del servidor: puerto del servidor. Cuando en realidad, los sockets se identifican de manera única mediante un cuarteto de información:
Client IP : Client Port
y Server IP : Server Port
Entonces, mientras que el IP del servidor y el puerto del servidor son constantes en todas las conexiones aceptadas, la información del lado del cliente es lo que le permite hacer un seguimiento de dónde va todo.
Ejemplo para aclarar cosas:
Digamos que tenemos un servidor en 192.168.1.1:80 y dos clientes, 10.0.0.1 y 10.0.0.2.
10.0.0.1 abre una conexión en el puerto local 1234 y se conecta al servidor. Ahora el servidor tiene un socket identificado de la siguiente manera:
10.0.0.1:1234 - 192.168.1.1:80
Ahora 10.0.0.2 abre una conexión en el puerto local 5678 y se conecta al servidor. Ahora el servidor tiene dos sockets identificados de la siguiente manera:
10.0.0.1:1234 - 192.168.1.1:80
10.0.0.2:5678 - 192.168.1.1:80