socket sockets tcp network-programming port

sockets - socket - tcp port



TCP: ¿pueden dos puertos diferentes compartir un puerto? (4)

Un socket conectado se asigna a un nuevo puerto (dedicado)

Esa es una intuición común, pero es incorrecta. Una toma conectada no está asignada a un puerto nuevo / dedicado. La única restricción real que debe cumplir la pila TCP es que la tupla de (dirección_local, puerto_local, dirección_remota, puerto_remoto) debe ser única para cada conexión de socket. Por lo tanto, el servidor puede tener muchos sockets TCP que utilizan el mismo puerto local, siempre que cada uno de los sockets del puerto esté conectado a una ubicación remota diferente.

Consulte el párrafo "Par de conectores" en: http://books.google.com/books?id=ptSC4LpwGA0C&lpg=PA52&dq=socket%20pair%20tuple&pg=PA52#v=onepage&q=socket%20pair%20tuple&f=false

Esta podría ser una pregunta muy básica pero me confunde.

¿Pueden dos tomas conectadas diferentes compartir un puerto? Estoy escribiendo un servidor de aplicaciones que debería poder manejar más de 100k conexiones simultáneas, y sabemos que la cantidad de puertos disponibles en un sistema es de alrededor de 60k (16 bits). Un socket conectado se asigna a un nuevo puerto (dedicado), por lo que significa que el número de conexiones simultáneas está limitado por la cantidad de puertos, a menos que varios sockets puedan compartir el mismo puerto. Entonces la pregunta.

¡Gracias por la ayuda por adelantado!


Escucha TCP / HTTP en 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 que la persona que intenta conectarse 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 la gente supone que se ve 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, él tiene una dirección IP y se conecta a un servidor en IP: PUERTO. Como el cliente se conecta al puerto 80, ¿su puerto también debe tener 80? Esto es algo sensato para pensar, pero en realidad no es lo que sucede. Si eso fuera correcto, solo podríamos atender a un usuario por dirección IP extranjera. Una vez que se conecta una computadora remota, engancha el puerto 80 a la conexión del 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 pasa a otro hilo. La comunicación nunca encierra el puerto de escucha.

2.) Las conexiones se identifican de manera única por el SO mediante la siguiente tupla de 5: (IP local, puerto local, IP remoto, 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 alto orden al azar, sin usar . De esta forma, un único cliente puede tener hasta ~ 64k de conexiones con el 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, use netstat para ver qué está sucediendo en esta computadora. Utilizaremos el puerto 500 en lugar de 80 (debido a que un montón de cosas están sucediendo en el puerto 80 ya que es un puerto común, pero funcionalmente no hace la diferencia).

netstat -atnp | grep -i ":500 "

Como se esperaba, la salida está en blanco. Ahora comencemos 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 -

Entonces 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 todas las direcciones IP". Un error fácil de hacer es escuchar solo en el puerto 127.0.0.1, que solo aceptará conexiones de la computadora actual. Entonces, esto no es una conexión, esto solo significa que un proceso solicitó bind () a IP del puerto, y ese proceso es responsable de manejar todas las conexiones a ese puerto. Esto insinúa la limitación de que solo puede haber un proceso por computadora escuchando en un puerto (hay formas de evitarlo mediante la 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/quickweb ) que abre un socket TCP, envía la carga útil ("Test payload." En este caso), espera unos segundos y se 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 te conectas con otro cliente y haces netstat nuevamente, verás 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. Por lo tanto, nunca hay confusión entre las direcciones IP.


Teóricamente, sí. Practica, no. La mayoría de los núcleos (incluido Linux) no le permiten un segundo bind() a un puerto ya asignado. No fue un parche realmente grande para hacer esto permitido.

Concepcionalmente, deberíamos diferenciar entre socket y puerto . Los sockets son puntos finales de comunicación bidireccionales, es decir, "cosas" donde podemos enviar y recibir bytes. Es una cuestión de concepción, no existe tal campo en un encabezado de paquete llamado "socket".

Port es un identificador que es capaz de identificar un socket. En el caso del TCP, un puerto es un entero de 16 bits, pero también hay otros protocolos (por ejemplo, en los zócalos de Unix, un "puerto" es esencialmente una cadena).

El principal problema es el siguiente: si llega un paquete entrante, el kernel puede identificar su socket por su número de puerto de destino. Es una forma más común, pero no es la única posibilidad:

  • Los sockets se pueden identificar por la IP de destino de los paquetes entrantes. Este es el caso, por ejemplo, si tenemos un servidor que usa dos IPs simultáneamente. Entonces podemos ejecutar, por ejemplo, diferentes servidores web en los mismos puertos, pero en las diferentes direcciones IP.
  • Los zócalos también se pueden identificar por su puerto de origen e ip. Este es el caso en muchas configuraciones de equilibrio de carga.

Como está trabajando en un servidor de aplicaciones, podrá hacerlo.


Un socket de servidor escucha en un solo puerto. Todas las conexiones de cliente establecidas en ese servidor están asociadas con ese mismo puerto de escucha en el lado del servidor de la conexión. Una conexión establecida se identifica de manera única por la combinación de pares de IP / Puerto del lado del cliente y del lado del servidor. Las conexiones múltiples en el mismo servidor pueden compartir el mismo par de IP / Puerto del lado del servidor siempre que estén asociadas con diferentes pares de IP / Puerto del lado del cliente , y el servidor podría manejar tantos clientes como los recursos del sistema disponibles lo permitan a.

En el lado del cliente , es práctica común que las nuevas conexiones salientes utilicen un puerto aleatorio del lado del cliente , en cuyo caso es posible quedarse sin puertos disponibles si hace muchas conexiones en un corto período de tiempo.