C'est peut-être une question très basique mais cela me déroute.
Deux prises connectées différentes peuvent-elles partager un port? J'écris un serveur d'application qui devrait être capable de gérer plus de 100k connexions simultanées, et nous savons que le nombre de ports disponibles sur un système est d'environ 60k (16 bits). Un socket connecté est affecté à un nouveau port (dédié), ce qui signifie que le nombre de connexions simultanées est limité par le nombre de ports, à moins que plusieurs sockets puissent partager le même port. Donc la question.
Merci pour l'aide à l'avance!
Écoute TCP / HTTP sur les ports: comment plusieurs utilisateurs peuvent-ils partager le même port?
Alors, que se passe-t-il lorsqu'un serveur écoute les connexions entrantes sur un port TCP? Par exemple, disons que vous avez 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 essaie de se connecter à vous a l'adresse IP 10.1.2.3. Cette personne peut se connecter à vous en ouvrant une socket TCP vers 24.14.181.229:80. Assez simple.
Intuitivement (et à tort), la plupart des gens supposent que cela ressemble à quelque chose comme ceci:
C'est intuitif, car du point de vue du client, il a une adresse IP, et se connecte à un serveur à IP: PORT. Puisque le client se connecte au port 80, alors son port doit être 80 aussi? C'est une chose sensée à penser, mais en fait pas ce qui se passe. Si cela était correct, nous ne pourrions servir qu'un seul utilisateur par adresse IP étrangère. Une fois qu'un ordinateur distant se connecte, il monopolise la connexion du port 80 au port 80 et personne d'autre ne peut se connecter.
Trois choses doivent être comprises:
1.) Sur un serveur, un processus écoute sur un port. Une fois qu'il obtient une connexion, il la transmet à un autre thread. La communication ne monopolise jamais le port d'écoute.
2.) Les connexions sont identifiées de manière unique par le système d'exploitation par les 5 tuples suivants: (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 choisit un port source aléatoire et inutilisé . De cette façon, un seul client peut avoir jusqu'à ~ 64 000 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:
Regard sur 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 c'est un port commun, mais fonctionnellement cela ne fait aucune différence).
Comme prévu, la sortie est vide. Maintenant, démarrons un serveur Web:
Maintenant, voici la sortie de l'exécution de netstat à nouveau:
Alors maintenant, il y a un processus qui écoute activement (état: 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 sur le port 127.0.0.1, qui n'acceptera que les connexions de l'ordinateur actuel. Donc ce n'est pas une connexion, cela signifie simplement qu'un processus a demandé à bind () au port IP, et que ce processus est responsable de gérer toutes les connexions à ce port. Cela indique la limitation qu'il ne peut y avoir qu'un seul processus par ordinateur en écoute sur un port (il existe des moyens de contourner cela en utilisant le multiplexage, mais c'est un sujet beaucoup plus compliqué). 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:
Il s'agit d'un simple script ( https://github.com/grokit/quickweb ) qui ouvre un socket TCP, envoie la charge utile ("Test payload." Dans ce cas), attend quelques secondes et se déconnecte. Faire à nouveau netstat pendant que cela se produit affiche les éléments suivants:
Si vous vous connectez avec un autre client et refaites netstat, vous verrez ce qui suit:
... 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.
la source
C'est une intuition courante, mais elle est incorrecte. Une prise connectée n'est pas affectée à un nouveau port / dédié. La seule contrainte réelle que la pile 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 de nombreuses sockets TCP utilisant le même port local, tant que chacune des sockets sur le port est connectée à un emplacement distant différent.
Consultez le paragraphe "Socket Pair" à l' adresse : http://books.google.com/books?id=ptSC4LpwGA0C&lpg=PA52&dq=socket%20pair%20tuple&pg=PA52#v=onepage&q=socket%20pair%20tuple&f=false
la source
bind()
opération précède l'connect()
opération, même implicitement.bind()
n'était utilisé que côté serveur avantaccept()?
Donc, le côté client liera également le port particulier?bind()
peut être utilisé côté client avantconnect()
.Théoriquement, oui. Pratique, non. La plupart des noyaux (y compris linux) ne vous permettent pas une seconde
bind()
sur un port déjà alloué. Ce n'était pas un très gros patch pour rendre cela permis.Sur le plan de la conception, nous devrions faire la différence entre socket et port . Les sockets sont des points de terminaison de communication bidirectionnels, c'est-à-dire des «objets» où nous pouvons envoyer et recevoir des octets. C'est une chose conceptuelle, il n'y a pas de 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 de 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 noyau peut identifier sa socket par son numéro de port de destination. C'est le moyen le plus courant, mais ce n'est pas la seule possibilité:
Parce que vous travaillez sur un serveur d'applications, il pourra le faire.
la source
bind()
.bind()
? Je peux l'imaginer, oui c'est tout à fait possible, mais le fait est que WinSock et l'API Posix utilisent l'bind()
appel pour cela, même leur paramétrage est pratiquement le même. Même si une API n'a pas cet appel, vous devez en quelque sorte le dire, d'où voulez-vous lire les octets entrants .listen()
/ lesaccept()
appels API peuvent créer les sockets de manière à ce que le noyau les différencie par leurs ports entrants. La question du PO peut être interprétée de la manière dont il la demande essentiellement. Je pense que c'est assez réaliste, mais ce n'est pas ce que veut dire littéralement sa question.Non. Il n'est pas possible de partager le même port à un instant donné. Mais vous pouvez faire de votre application de telle manière qu'elle rendra l'accès au port à un instant différent.
la source