Communication par socket TCP : comprendre le comportement des sockets
Lorsque vous travaillez avec des sockets TCP en Python, il est crucial de comprendre la nature basée sur le flux de ces sockets. relations. Contrairement aux relations un-à-un entre les opérations d'envoi et de réception, le flux de données est dicté par les protocoles mis en œuvre.
Considérez l'extrait de code suivant pour un simple serveur d'écho :
import socket HOST = '' PORT = 50007 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen(1) while True: data = s.recv(1024) if not data: break s.sendall(data)
Dans sa forme originale, ce code établit une connexion avec un client, attend les données du client et les renvoie jusqu'à ce que le client se déconnecte. La boucle itère à plusieurs reprises, le serveur recevant et répondant à chaque message entrant.
Cependant, supposons que nous modifiions le code pour exclure l'étape où le serveur renvoie les données au client :
import socket HOST = '' PORT = 50007 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen(1) while True: data = s.recv(1024) if not data: break
Dans ce scénario, le comportement de la méthode recv change. Lorsque le serveur modifié établit une connexion avec un client, il attend des données. Cependant, comme aucune donnée n’est envoyée, la méthode recv se bloque indéfiniment. Le deuxième appel à recv n'a jamais lieu, empêchant le serveur de reconnaître la déconnexion du client.
Pour comprendre ce comportement, il est essentiel de rappeler que les sockets TCP fonctionnent comme des flux de données. L’envoi et la réception de données ne sont pas directement liés l’un à l’autre. Les règles régissant la communication sont déterminées par le protocole mis en œuvre. Dans le code d'origine, le protocole dictait que le serveur renvoyait toutes les données reçues du client.
Avec notre modification, le protocole change. Le serveur ne reçoit désormais que les données du client et les supprime. Le client attend une réponse après l'envoi des données, mais le serveur modifié reste silencieux. Pour résoudre ce problème, le client doit indiquer explicitement qu'il a terminé l'envoi des données en fermant sa connexion sortante. Une fois que cela se produit, le serveur reçoit un appel recv vide, l'interprète comme une déconnexion et envoie le message « OK ».
De plus, dans des scénarios réels, les paquets de données peuvent être fragmentés pendant la transmission. Pour tenir compte de cela, une implémentation client plus robuste effectuerait plusieurs appels recv jusqu'à ce que toutes les données soient reçues.
Vous trouverez ci-dessous des versions mises à jour du code serveur et client qui répondent à ces problèmes. problèmes :
Serveur :
import socket HOST = '' PORT = 50007 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen(1) while True: data = s.recv(1024) if not data: break s.sendall(b'ok') s.shutdown(socket.SHUT_WR) s.close()
Client :
import socket HOST = 'localhost' PORT = 50007 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) s.sendall(b'Hello, world') s.shutdown(socket.SHUT_WR) data = b'' while True: buf = s.recv(1024) if not buf: break data += buf s.close()
En mettant en œuvre ces changements, nous nous assurons que la communication entre le serveur et le client fonctionne comme prévu, reconnaissant les déconnexions et gérant la fragmentation des données.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!