TCP: deux sockets différents peuvent-ils partager un port?

Cela pourrait être une question très simple mais cela me déroute.

Deux sockets connectées différentes peuvent-elles partager un port? J’écris un serveur d’applications qui devrait pouvoir gérer plus de 100 000 connexions simultanées, et nous soaps que le nombre de ports disponibles sur un système est d’environ 60 Ko (16 bits). Un socket connecté est atsortingbué à un nouveau port (dédié), ce qui signifie que le nombre de connexions simultanées est limité par le nombre de ports, sauf si plusieurs sockets peuvent partager le même port. Donc la question

Merci pour l’aide à l’avance!

    Un socket serveur écoute sur un seul port. Toutes les connexions client établies sur ce serveur sont associées au même port d’écoute du côté serveur de la connexion. Une connexion établie est identifiée de manière unique par la combinaison de paires IP / port côté client et côté serveur. Plusieurs connexions sur le même serveur peuvent partager la même paire IP / Port côté serveur tant qu’elles sont associées à différentes paires IP / Port côté client et que le serveur pourra gérer autant de clients que les ressources système disponibles le permettent. à.

    Du côté du client , il est courant que les nouvelles connexions sortantes utilisent un port côté client aléatoire, auquel cas il est possible de manquer de ports disponibles si vous établissez beaucoup de connexions en peu de temps.

    TCP / HTTP Listening On: comment de nombreux utilisateurs peuvent partager le même port

    Que se passe-t-il lorsqu’un serveur écoute les connexions entrantes sur un port TCP? Par exemple, supposons que vous ayez un serveur Web sur le port 80. Supposons que votre ordinateur a l’adresse IP publique 24.14.181.229 et que la personne qui tente de se connecter à vous ait l’adresse IP 10.1.2.3. Cette personne peut se connecter à vous en ouvrant un socket TCP jusqu’au 24.14.181.229:80. Assez simple.

    Intuitivement (et à tort), la plupart des gens supposent que cela ressemble à ceci:

    Local Computer | Remote Computer -------------------------------- :80 | :80 ^^ not actually what happens, but this is the conceptual model a lot of people have in mind. 

    Ceci est intuitif car du sharepoint vue du client, il possède une adresse IP et se connecte à un serveur IP: PORT. Puisque le client se connecte au port 80, alors son port doit être 80 également? C’est une chose sensée à penser, mais en réalité pas ce qui se passe. Si cela était correct, nous ne pourrions servir qu’un utilisateur par adresse IP étrangère. Une fois qu’un ordinateur distant se connecte, il connecte alors le port 80 à la connexion du port 80, et personne d’autre ne peut se connecter.

    Trois choses doivent être comsockets:

    1.) Sur un serveur, un processus écoute sur un port. Une fois la connexion établie, elle est transmise à un autre thread. La communication n’emballe jamais le port d’écoute.

    2.) Les connexions sont identifiées de manière unique par le système d’exploitation par le 5-tuple suivant: (IP local, port local, IP distant, port distant, protocole). Si un élément du tuple est différent, il s’agit d’une connexion complètement indépendante.

    3.) Lorsqu’un client se connecte à un serveur, il sélectionne un port source aléatoire de premier ordre et inutilisé . De cette façon, un seul client peut avoir jusqu’à ~ 64 Ko de connexions au serveur pour le même port de destination.

    Donc, c’est vraiment ce qui est créé lorsqu’un client se connecte à un serveur:

      Local Computer | Remote Computer | Role ----------------------------------------------------------- 0.0.0.0:80 |  | LISTENING 127.0.0.1:80 | 10.1.2.3: | ESTABLISHED 

    Regarder ce qui se passe réellement

    Tout d’abord, utilisons netstat pour voir ce qui se passe sur cet ordinateur. Nous utiliserons le port 500 au lieu de 80 (car tout un tas de choses se passe sur le port 80, car il s’agit d’un port commun, mais fonctionnellement, cela ne fait aucune différence).

      netstat -atnp | grep -i ":500 " 

    Comme prévu, la sortie est vide. Maintenant, commençons un serveur web:

      sudo python3 -m http.server 500 

    Maintenant, voici le résultat de l’exécution de netstat à nouveau:

      Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:500 0.0.0.0:* LISTEN - 

    Il y a donc maintenant un processus qui écoute activement (State: LISTEN) sur le port 500. L’adresse locale est 0.0.0.0, qui est le code pour “écouter toutes les adresses IP”. Une erreur facile à faire est d’écouter uniquement le port 127.0.0.1, qui n’acceptera que les connexions de l’ordinateur en cours. Donc, ce n’est pas une connexion, cela signifie simplement qu’un processus a demandé de lier () au port IP, et que ce processus est responsable de la gestion de toutes les connexions vers ce port. Cela suggère qu’il ne peut y avoir qu’un seul processus par ordinateur sur un port (il existe des moyens de contourner cela en utilisant le multiplexage, mais c’est un sujet beaucoup plus complexe). Si un serveur Web écoute sur le port 80, il ne peut pas partager ce port avec d’autres serveurs Web.

    Alors maintenant, connectons un utilisateur à notre machine:

      quicknet -m tcp -t localhost:500 -p Test payload. 

    Ceci est un script simple ( https://github.com/grokit/quickweb ) qui ouvre un socket TCP, envoie le payload (“Test payload.” Dans ce cas), attend quelques secondes et se déconnecte. Faire de nouveau netstat pendant que cela se produit affiche les éléments suivants:

      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 vous vous connectez avec un autre client et faites de nouveau netstat, vous verrez ce qui suit:

      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 - 

    … c’est-à-dire que le client a utilisé un autre port aléatoire pour la connexion. Il n’y a donc jamais de confusion entre les adresses IP.

    Une prise connectée est assignée à un nouveau port (dédié)

    C’est une intuition commune, mais c’est incorrect. Une prise connectée n’est pas affectée à un nouveau port / dédié. La seule contrainte réelle à laquelle la stack TCP doit satisfaire est que le tuple de (local_address, local_port, remote_address, remote_port) doit être unique pour chaque connexion de socket. Ainsi, le serveur peut avoir plusieurs sockets TCP utilisant le même port local, à condition que chacun des sockets sur le port soit connecté à un autre emplacement distant.

    Voir le paragraphe “Socket Pair” à l’ adresse suivante : http://books.google.com/books?id=ptSC4LpwGA0C&lpg=PA52&dq=socket%20pair%20tuple&pg=PA52#v=onepage&q=socket%20pair%20tuple&f=false

    Théoriquement, oui. Pratique, pas. La plupart des kernelx (y compris linux) ne vous permettent pas une seconde bind() à un port déjà alloué. Ce n’était pas vraiment un gros patch pour rendre cela possible.

    Sur le plan de la conception, il convient de différencier socket et port . Les sockets sont des points d’extrémité de communication bidirectionnels, c’est-à-dire des “choses” où nous pouvons envoyer et recevoir des octets. C’est une conception, il n’y a pas un tel champ dans un en-tête de paquet nommé “socket”.

    Le port est un identifiant capable d’identifier une socket. Dans le cas du TCP, un port est un entier sur 16 bits, mais il existe également d’autres protocoles (par exemple, sur les sockets unix, un “port” est essentiellement une chaîne).

    Le problème principal est le suivant: si un paquet entrant arrive, le kernel peut identifier sa socket par son numéro de port de destination. C’est un moyen très courant, mais ce n’est pas la seule possibilité:

    • Les sockets peuvent être identifiés par l’adresse IP de destination des paquets entrants. C’est le cas, par exemple, si nous avons un serveur utilisant deux adresses IP simultanément. Ensuite, nous pouvons exécuter, par exemple, différents serveurs Web sur les mêmes ports, mais sur les différentes adresses IP.
    • Les sockets peuvent être identifiés par leur port source et leur adresse IP. C’est le cas dans de nombreuses configurations d’équilibrage de charge.

    Parce que vous travaillez sur un serveur d’applications, vous pourrez le faire.