Pourquoi `socket.recv()` se bloque lorsque le serveur ne renvoie pas de données ?

Patricia Arquette
Libérer: 2024-11-22 22:33:26
original
844 Les gens l'ont consulté

Why Does `socket.recv()` Stall When the Server Doesn't Send Data Back?

Comprendre le comportement des sockets : pourquoi Socket.recv() se bloque sans données envoyées

Les sockets Python, comme les connexions TCP, se comportent comme des flux de données qui circulent entre les clients et les serveurs. Cet article examine les raisons du problème selon lequel un appel socket.recv() ne parvient pas à renvoyer des données après la modification de la transmission des données.

L'exemple du serveur Echo

Considérez l'exemple du serveur d'écho Python de la documentation officielle. Ce serveur écoute les connexions entrantes, reçoit les données et les renvoie au client. L'extrait de code suivant reproduit le comportement d'origine du serveur :

import socket

HOST = ''
PORT = 50007 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)

conn, addr = s.accept()
print('Connected by', addr)

while True:
    data = conn.recv(1024)
    if not data: break
    conn.sendall(data)
conn.close()
Copier après la connexion

Modification du comportement du serveur

Le problème survient lorsque le code est modifié pour ne pas renvoyer de données au client. :

while True:
    data = conn.recv(1024)
    if not data: break
conn.close()
Copier après la connexion

Dans ce code modifié, la boucle while reçoit sans cesse des données du client, mais le serveur n'envoie jamais de données dos. Cela provoque le blocage du client indéfiniment lors de l'appel socket.recv().

Comprendre le flux de communication

Les sockets TCP ne maintiennent pas une relation un-à-un entre l'envoi et la réception d'appels sur différents points de terminaison. Au lieu de cela, le protocole définit les règles de communication. Dans ce cas, le serveur d'écho d'origine a implémenté une règle selon laquelle le serveur renvoie les données reçues jusqu'à ce que le client ferme la connexion.

Lorsque le comportement du serveur est modifié, les règles ont effectivement été modifiées. Le serveur ne reçoit désormais que les données et les supprime jusqu'à ce que le client ferme la connexion. Le serveur ne renvoie jamais de données au client.

Adaptation du comportement du client

Pour travailler avec le serveur modifié, le client doit ajuster son comportement. Étant donné que le serveur n'envoie plus de données activement, le client suppose que la réception des données indique une connexion terminée. Pour faciliter cela, le client doit fermer son côté sortant de la connexion pour signaler au serveur qu'il a fini d'envoyer des données. Le client peut ensuite effectuer plusieurs appels recv pour gérer toute fragmentation potentielle des données entrantes.

Code mis à jour

Vous trouverez ci-dessous le code mis à jour pour le serveur et le client qui adhère aux règles modifiées de communication :

Serveur :

import socket

HOST = ''
PORT = 50007 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)

conn, addr = s.accept()
print('Connected by', addr)

while True:
    data = conn.recv(1024)
    if not data: break
conn.sendall(b'ok')
conn.shutdown(socket.SHUT_WR)
conn.close()
Copier après la connexion

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()
print('Received', repr(data))
Copier après la connexion

En comprenant la nature basée sur les flux de Sockets TCP et en ajustant les règles de communication en conséquence, il est possible de résoudre le problème où socket.recv() se bloque sans que les données ne soient envoyé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!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal