web-dev-qa-db-fra.com

Quand socket.recv (recv_size) revient-il?

Du test, j'ai conclu que dans les trois cas suivants, la socket.recv(recv_size) reviendra.

  1. Après la connexion a été fermée. Par exemple, le côté client appelé socket.close () ou toute erreur de socket s'est produite, il retournerait une chaîne vide.

  2. Certaines données viennent, la taille des données est supérieure à recv_size.

  3. Certaines données viennent, la taille des données est inférieure à recv_size et plus de données ne viennent après un court laps de temps (j'ai trouvé que 0,1s fonctionnerait).

Plus de détails sur # 3:

#server.py

while True:
    data = sock.recv(10)
    print data, 'EOF'

#client1.py

sock.sendall("12345")
sock.sendall("a" * 50)

#client2.py

sock.sendall("12345")
time.sleep(0.1)
sock.sendall("a" * 50)

Quand je lance client1.py, le server.py échos:

12345aaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaa EOF

Quand je lance client2.py, le server.py échos:

12345 EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF
aaaaaaaaaa EOF

Mes conclusions sont-elles correctes? Où puis-je voir la description officielle de # 3?

42
redice

Oui, votre conclusion est correcte. socket.recv Est un appel bloquant.

socket.recv(1024) lira au plus 1024 octets, bloquant si aucune donnée n'est en attente de lecture. Si vous ne lisez pas toutes les données, un autre appel à socket.recv Ne bloquera pas.

socket.recv Se terminera également par une chaîne vide si la connexion est fermée ou en cas d'erreur.

Si vous voulez un socket non bloquant, vous pouvez utiliser le module de sélection (un peu plus compliqué que simplement utiliser des sockets) ou vous pouvez utiliser socket.setblocking.

J'ai eu des problèmes avec socket.setblocking Dans le passé, mais n'hésitez pas à l'essayer si vous le souhaitez.

22
Martin

Il aura le même comportement que l'appel recc libc sous-jacent voir la page de manuel pour une description officielle du comportement (ou lire plus description générale de l'api des sockets).

4
silverjam

Je pense que vos conclusions sont correctes mais pas exactes.

Comme l'indique docs , socket.recv se concentre principalement sur les tampons réseau.

Lorsque le socket bloque, socket.recv reviendra tant que les tampons réseau auront des octets. Si les octets dans les tampons réseau sont supérieurs à socket.recv peut gérer, il renverra le nombre maximal d'octets qu'il peut gérer. Si les octets dans les tampons réseau sont inférieurs à socket.recv peut gérer, il retournera tous les octets dans les tampons réseau.

0