Si je comprends bien, c'est ce qui se passe lorsqu'un client fait une demande de connexion:
- Le serveur sera lié à un numéro de port particulier. Le numéro de port est toujours lié à un processus d'écoute. Étant donné que seul le serveur écoute les connexions entrantes, nous n'avons pas besoin de lier du côté client
- Le serveur continuera à écouter ce numéro de port.
- Le client enverra une
connect()
demande. - Le serveur acceptera la demande en utilisant
accept()
. Dès que le serveur accepte la demande du client, le noyau alloue un numéro de port aléatoire pour le serveur pour plus loinsend()
etreceive()
, puisque le même numéro de port sur le serveur ne peut pas être utilisé pour l'envoi et l'écoute, et le port précédent est toujours écouter de nouvelles connexions
Compte tenu de tout cela, comment le serveur peut-il savoir sur quel port le client reçoit? Je sais que le client enverra des segments TCP avec un port source et un port de destination, donc le serveur utilisera le port source de ce segment comme port de destination, mais quelle fonction le serveur appelle-t-il pour connaître ce port? C'est ça accept()
?
Réponses:
Cela fait partie de l'en-tête TCP (ou UDP, etc.), dans le paquet. Le serveur le découvre donc parce que le client le lui dit. Ceci est similaire à la façon dont il découvre l'adresse IP du client (qui fait partie de l'en-tête IP).
Par exemple, chaque paquet TCP comprend un en-tête IP (avec au moins l'IP source, l'IP de destination et le protocole [TCP]). Ensuite, il y a un en-tête TCP (avec les ports source et de destination, et plus encore).
Lorsque le noyau reçoit un paquet SYN (le début d'une connexion TCP) avec une IP distante de 10.11.12.13 (dans l'en-tête IP) et un port distant de 12345 (dans l'en-tête TCP), il connaît alors l'IP et le port distants . Il renvoie un SYN | ACK. S'il obtient un ACK en retour, l'
listen
appel renvoie un nouveau socket, configuré pour cette connexion.Un socket TCP est identifié de manière unique par les quatre valeurs (IP distante, IP locale, port distant, port local). Vous pouvez avoir plusieurs connexions / sockets, à condition qu'au moins l'une d'entre elles diffère.
En règle générale, le port local et l'IP locale seront les mêmes pour toutes les connexions à un processus serveur (par exemple, toutes les connexions à sshd seront sur local-ip: 22). Si une machine distante établit plusieurs connexions, chacune utilisera un port distant différent. Donc, tout sauf le port distant sera le même, mais ça va, un seul des quatre doit différer.
Vous pouvez utiliser, par exemple, wirehsark pour voir le paquet, et il étiquetera toutes les données pour vous. Voici le port source mis en évidence (notez-le mis en évidence dans le paquet décodé, ainsi que le vidage hexadécimal en bas):
la source
write
(etc.) allez au bon endroit.La "demande de connexion (l'
connect()
appel système du programme client , généralement) provoque une négociation à trois voies . Le premier paquet de la négociation à trois voies (du client au serveur) a l'indicateur SYN défini et inclut le numéro de port TCP du programme client. le noyau lui assigne.Vous pouvez le voir dans un article sur les paquets Nmap vs Natural SYN . Le décodage de paquets Nmap SYN a la phrase "source.60058> dest.22". Le décodage "paquet SYN légitime" contient la phrase "source.35970> dest.80". Les deux paquets SYN indiquent au noyau distant que les paquets proviennent respectivement du port TCP 60058 et du port 35970.
la source
getpeername()
devrait vous permettre de le faire sur n'importe quel socket ouvert. L'accept()
appel système que le code serveur doit utiliser pour obtenir un descripteur de fichier socket pour communiquer avec le client a un paramètre ("sockaddr" dans mes pages de manuel) qui contient l'adresse IP du client potentiel et le numéro de port TCP.Le socket TCP est un socket orienté flux. Les deux descripteurs de socket (détenus par vous et votre homologue) sont connectés de manière fiable. Vous n'avez donc pas à vous soucier du port client - écrivez simplement votre descripteur de socket!
Aussi, n'hésitez pas à getsockname (2) si vous voulez vraiment le savoir (pour vous connecter peut-être).
la source
La connexion est définie par un tuple (IP source, port source, IP de destination, port de destination). Les réponses vont dans le sens inverse.
la source