http - tag - ¿Cómo se conectan varios clientes simultáneamente a un puerto, digamos 80, en un servidor?
scripts para mta dayz (5)
Esta pregunta ya tiene una respuesta aquí:
Entiendo los conceptos básicos de cómo funcionan los puertos. Sin embargo, lo que no entiendo es cómo varios clientes pueden conectarse simultáneamente al puerto 80. Sé que cada cliente tiene un puerto único (para su máquina). ¿El servidor responde desde un puerto disponible al cliente y simplemente indica que la respuesta provino de 80? ¿Como funciona esto?
Escucha TCP / HTTP en los puertos: ¿Cómo pueden muchos usuarios compartir el mismo puerto?
Entonces, ¿qué sucede cuando un servidor escucha las conexiones entrantes en un puerto TCP? Por ejemplo, supongamos que tiene un servidor web en el puerto 80. Supongamos que su computadora tiene la dirección IP pública de 24.14.181.229 y la persona que intenta conectarse con usted tiene la dirección IP 10.1.2.3. Esta persona puede conectarse a usted abriendo un socket TCP a 24.14.181.229:80. Suficientemente simple.
Intuitivamente (y erróneamente), la mayoría de las personas asumen que se ve algo así:
Local Computer | Remote Computer
--------------------------------
<local_ip>:80 | <foreign_ip>:80
^^ not actually what happens, but this is the conceptual model a lot of people have in mind.
Esto es intuitivo, porque desde el punto de vista del cliente, tiene una dirección IP y se conecta a un servidor en IP: PORT. Dado que el cliente se conecta al puerto 80, entonces su puerto también debe ser 80? Esto es algo sensato para pensar, pero en realidad no es lo que sucede. Si eso fuera correcto, solo podríamos servir a un usuario por dirección IP extranjera. Una vez que una computadora remota se conecta, entonces él acapararía el puerto 80 al puerto 80 y nadie más podría conectarse.
Tres cosas deben ser entendidas:
1.) En un servidor, un proceso está escuchando en un puerto. Una vez que obtiene una conexión, la entrega a otro hilo. La comunicación nunca acapara el puerto de escucha.
2.) Las conexiones están identificadas de forma única por el SO mediante la siguiente tupla 5: (IP local, puerto local, IP remota, puerto remoto, protocolo). Si algún elemento en la tupla es diferente, entonces esta es una conexión completamente independiente.
3.) Cuando un cliente se conecta a un servidor, elige un puerto de origen de orden alto no utilizado al azar . De esta manera, un solo cliente puede tener hasta ~ 64k conexiones al servidor para el mismo puerto de destino.
Entonces, esto es realmente lo que se crea cuando un cliente se conecta a un servidor:
Local Computer | Remote Computer | Role
-----------------------------------------------------------
0.0.0.0:80 | <none> | LISTENING
127.0.0.1:80 | 10.1.2.3:<random_port> | ESTABLISHED
Mirando lo que realmente sucede
Primero, usemos netstat para ver qué está sucediendo en esta computadora. Usaremos el puerto 500 en lugar de 80 (porque un montón de cosas suceden en el puerto 80 ya que es un puerto común, pero funcionalmente no hace una diferencia).
netstat -atnp | grep -i ":500 "
Como era de esperar, la salida está en blanco. Ahora vamos a iniciar un servidor web:
sudo python3 -m http.server 500
Ahora, aquí está la salida de ejecutar netstat nuevamente:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:500 0.0.0.0:* LISTEN -
Así que ahora hay un proceso que está escuchando activamente (Estado: ESCUCHAR) en el puerto 500. La dirección local es 0.0.0.0, que es el código para "escuchar a todos". Un error fácil de cometer es escuchar en la dirección 127.0.0.1, que solo aceptará conexiones desde la computadora actual. Entonces, esto no es una conexión, solo significa que un proceso solicitó enlazar () al puerto IP, y ese proceso es responsable de manejar todas las conexiones a ese puerto. Esto apunta a la limitación de que solo puede haber un proceso por computadora que escucha en un puerto (hay maneras de evitar eso utilizando multiplexación, pero este es un tema mucho más complicado). Si un servidor web está escuchando en el puerto 80, no puede compartir ese puerto con otros servidores web.
Así que ahora, conectemos un usuario a nuestra máquina:
quicknet -m tcp -t localhost:500 -p Test payload.
Este es un script simple ( https://github.com/grokit/dcore/tree/master/apps/quicknet ) que abre un socket TCP, envía la carga útil ("Test payload" en este caso), espera unos segundos y desconecta. Hacer netstat nuevamente mientras esto sucede muestra lo siguiente:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:500 0.0.0.0:* LISTEN -
tcp 0 0 192.168.1.10:500 192.168.1.13:54240 ESTABLISHED -
Si se conecta con otro cliente y vuelve a hacer netstat, verá lo siguiente:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:500 0.0.0.0:* LISTEN -
tcp 0 0 192.168.1.10:500 192.168.1.13:26813 ESTABLISHED -
... es decir, el cliente usó otro puerto aleatorio para la conexión. Así que nunca hay confusión entre las direcciones IP.
En primer lugar, un "puerto" es solo un número. Todo lo que una "conexión a un puerto" realmente representa es un paquete que tiene ese número especificado en su campo de encabezado "puerto de destino".
Ahora, hay dos respuestas a su pregunta, una para protocolos con estado y otra para protocolos sin estado.
Para un protocolo sin estado (es decir, UDP), no hay problema porque las "conexiones" no existen: varias personas pueden enviar paquetes al mismo puerto, y sus paquetes llegarán en la secuencia que sea. Nadie está nunca en el estado "conectado".
Para un protocolo con estado (como TCP), una conexión se identifica mediante una tupla de 4 que consta de puertos de origen y destino y direcciones IP de origen y destino. Entonces, si dos máquinas diferentes se conectan al mismo puerto en una tercera máquina, hay dos conexiones distintas porque las IP de origen son diferentes. Si la misma máquina (o dos detrás de NAT o que comparten la misma dirección IP) se conecta dos veces a un único extremo remoto, las conexiones se diferencian por el puerto de origen (que generalmente es un puerto aleatorio de número alto).
Simplemente, si me conecto al mismo servidor web dos veces desde mi cliente, las dos conexiones tendrán puertos de origen diferentes desde mi perspectiva y los puertos de destino del servidor web. Por lo tanto, no hay ambigüedad, aunque ambas conexiones tienen las mismas direcciones IP de origen y destino.
Los puertos son una forma de multiplexar direcciones IP para que diferentes aplicaciones puedan escuchar en la misma dirección IP / par de protocolos. A menos que una aplicación defina su propio protocolo de nivel superior, no hay manera de multiplexar un puerto. Si dos conexiones que usan el mismo protocolo tienen IP de origen y destino idénticas y puertos de origen y destino idénticos, deben ser la misma conexión.
Normalmente, para cada cliente conectado, el servidor realiza un proceso secundario que se comunica con el cliente (TCP). El servidor principal entrega al proceso secundario un socket establecido que se comunica con el cliente.
Cuando envía los datos a un socket desde su servidor secundario, la pila TCP en el sistema operativo crea un paquete que regresa al cliente y establece el "desde el puerto" a 80.
Varios clientes pueden conectarse al mismo puerto (por ejemplo, 80) en el servidor porque en el lado del servidor, después de crear un socket y un enlace (configuración de IP local y puerto) se llama al socket, que le dice al sistema operativo que acepte las conexiones entrantes.
Cuando un cliente intenta conectarse al servidor en el puerto 80, se invoca la llamada de aceptación en el socket del servidor. Esto crea un nuevo zócalo para el cliente que intenta conectarse y, de manera similar, se crearán nuevos zócalos para los clientes posteriores que utilicen el mismo puerto 80.
Las palabras en cursiva son llamadas al sistema.
Árbitro
Importante:
Lamento decir que la respuesta de "Borealid" es imprecisa y algo incorrecta. En primer lugar, no hay relación con la ausencia de estado o la apatridia para responder a esta pregunta, y lo más importante es que la definición de la tupla para un socket es incorrecta.
Primero recuerda debajo de dos reglas:
Clave principal de un socket: Un socket se identifica por
{SRC-IP, SRC-PORT, DEST-IP, DEST-PORT, PROTOCOL}
no por{SRC-IP, SRC-PORT, DEST-IP, DEST-PORT}
- El protocolo es una parte importante de la definición de un socket.Asignación de procesos y sockets del sistema operativo: un proceso puede asociarse con (puede abrir / escuchar) múltiples sockets que pueden ser obvios para muchos lectores.
Ejemplo 1: Dos clientes que se conectan al mismo puerto del servidor significa: socket1 {SRC-A, 100, DEST-X,80, TCP}
y socket2{SRC-B, 100, DEST-X,80, TCP}
. Esto significa que el host A se conecta al puerto 80 del servidor X y otro host B también se conecta al mismo servidor X al mismo puerto 80. Ahora, la forma en que el servidor maneja estos dos sockets depende de si el servidor es de un solo hilo o de varios hilos (no explique esto mas tarde) Lo importante es que un servidor puede escuchar múltiples sockets simultáneamente.
Para responder a la pregunta original del post:
Independientemente de los protocolos con estado o sin estado, dos clientes pueden conectarse al mismo puerto del servidor porque para cada cliente podemos asignar un socket diferente (ya que la IP del cliente definitivamente será diferente). El mismo cliente también puede tener dos sockets que se conectan al mismo puerto del servidor, ya que dichos sockets difieren según SRC-PORT
. Con toda justicia, "Borealid" esencialmente mencionó la misma respuesta correcta, pero la referencia a un estado sin estado / completo fue algo innecesario / confuso.
Para responder a la segunda parte de la pregunta sobre cómo un servidor sabe qué socket responder. Primero, comprenda que para un proceso de un solo servidor que está escuchando en el mismo puerto, puede haber más de un socket (puede ser del mismo cliente o de diferentes clientes). Ahora, mientras un servidor sepa qué solicitud está asociada con qué socket, siempre puede responder al cliente apropiado utilizando el mismo socket. Por lo tanto, un servidor nunca necesita abrir otro puerto en su propio nodo que el original en el que el cliente inicialmente intentó enlazar la conexión. Si un servidor asigna diferentes puertos de servidor después de que un socket esté vinculado, entonces, en mi opinión, el servidor está desperdiciando su recurso y debe estar necesitando que el cliente se conecte nuevamente al nuevo puerto asignado.
Un poco más para completar:
Ejemplo 2: es una pregunta muy interesante que puede los dos procesos diferentes de un servidor escuchar el mismo puerto. Si no considera el protocolo como uno de los parámetros que definen el socket, entonces la respuesta es no. Inicialmente, esto es así porque podemos decir que, en tal caso, para un solo cliente que intenta conectarse a un puerto de servidor no tendrá ningún mecanismo para mencionar cuál de los dos procesos de escucha tiene previsto el cliente. Este es el mismo tema afirmado por la regla (2). Sin embargo, esta es una respuesta INCORRECTA porque ''protocolo'' también forma parte de la definición de socket. Por lo tanto, dos procesos en el mismo nodo pueden escuchar el mismo puerto solo si están usando un protocolo diferente. Por ejemplo, dos clientes no relacionados (por ejemplo, uno está usando TCP y otro está usando UDP) pueden vincularse para conectarse y comunicarse al mismo nodo de servidor y al mismo puerto, pero deben ser atendidos por dos procesos de servidor diferentes.
Tipos de servidor - único y múltiple:
Cuando los procesos de un servidor escuchan un puerto que significa que varios sockets pueden conectarse y comunicarse simultáneamente con el mismo proceso de servidor. Si un servidor utiliza un solo proceso secundario para servir a todos los sockets, entonces el servidor se denomina proceso único / subproceso y si el servidor usa muchos subprocesos para servir a cada socket mediante un subproceso, el servidor se llama multiproceso. Servidor de procesos / hilos. Tenga en cuenta que independientemente del tipo de servidor, un servidor puede / debe usar siempre el mismo socket inicial para responder (no es necesario asignar otro puerto de servidor).
Books sugeridos y resto de los dos volúmenes si puedes.
Una nota sobre el proceso padre / hijo (en respuesta a la consulta / comentario de ''Ioan Alexandru Cucu'')
Donde sea que mencioné algún concepto en relación con dos procesos, como A y B, considere que no están relacionados por la relación padre-hijo. Los sistemas operativos (especialmente UNIX) por diseño permiten que un proceso secundario herede todos los descriptores de archivos (FD) de los padres. Por lo tanto, todos los sockets (en UNIX como sistema operativo también son parte de FD) que un proceso que escucha A, puede ser escuchado por muchos más procesos A1, A2, .. siempre que estén relacionados por la relación padre-hijo con A. Pero un proceso independiente B (es decir, no tiene relación padre-hijo con A) no puede escuchar el mismo socket. Además, tenga en cuenta que esta regla de no permitir que dos procesos independientes escuchen el mismo zócalo se encuentra en un sistema operativo (o en sus bibliotecas de red) y, de lejos, es obedecida por la mayoría de los sistemas operativos. Sin embargo, uno puede crear su propio sistema operativo que puede violar muy bien estas restricciones.