web-dev-qa-db-ja.com

socket.recv(recv_size)が返されるのはいつですか?

テストから、次の3つの場合にsocket.recv(recv_size)が返されると結論付けました。

  1. 接続が閉じられた後。たとえば、クライアント側でsocket.close()と呼ばれるか、ソケットエラーが発生すると、空の文字列が返されます。

  2. データの中には、データのサイズがrecv_sizeを超えるものがあります。

  3. いくつかのデータが来ますが、データのサイズはrecv_sizeより小さいので、少し時間が経ってもそれ以上データは来ません(0.1sが機能することがわかりました)。

#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)

client1.pyを実行すると、server.pyがエコーします。

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

client2.pyを実行すると、server.pyがエコーします。

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

私の結論は正しいですか? #3に関する公式の説明はどこで見ることができますか?

42
redice

はい、あなたの結論は正しいです。 _socket.recv_はブロッキング呼び出しです。

socket.recv(1024)は最大1024バイトを読み取り、読み取り待ちのデータがない場合はブロックします。すべてのデータを読み取らないと、_socket.recv_への他の呼び出しはブロックされません。

_socket.recv_は、接続が閉じられるかエラーが発生した場合も空の文字列で終了します。

ノンブロッキングソケットが必要な場合は、selectモジュール(ソケットを使用するよりも少し複雑)を使用するか、_socket.setblocking_を使用できます。

過去に_socket.setblocking_で問題が発生しましたが、必要に応じて試してみてください。

22
Martin

基本的なrecv libc呼び出しと同じ動作になります。動作の公式説明については manページ を参照してください(またはソケットAPIの詳細 一般的な説明 を参照してください)。

4
silverjam

あなたの結論は正しいが、正確ではないと思います。

docs が示すように、socket.recvは主にネットワークバッファーに焦点を当てています。

ソケットがブロックされている場合、socket.recvは、ネットワークバッファーにバイトがある限り返されます。ネットワークバッファ内のバイトがsocket.recvで処理できる以上の場合、処理可能な最大バイト数を返します。ネットワークバッファーのバイト数がsocket.recvで処理できない場合、ネットワークバッファーのすべてのバイトが返されます。

0