ソケットの動作を理解する: データが送信されずに Socket.recv() が停止する理由
Python ソケットは、TCP 接続と同様に、データのストリームとして動作しますクライアントとサーバーの間を流れるもの。この記事では、データ送信が変更された後、socket.recv() 呼び出しがデータを返さない問題の背後にある理由を詳しく掘り下げます。
Echo サーバーの例
公式ドキュメントの Python エコー サーバーの例を考えてみましょう。このサーバーは着信接続をリッスンし、データを受信し、それをクライアントにエコーバックします。次のコード スニペットは、元のサーバーの動作を再現しています。
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()
サーバーの動作の変更
この問題は、データをクライアントに送り返さないようにコードが変更されている場合に発生します。 :
while True: data = conn.recv(1024) if not data: break conn.close()
この変更されたコードでは、while ループはクライアントからデータを無限に受信しますが、サーバーはデータを受信しません。データを送り返します。これにより、クライアントはソケット.recv() 呼び出しで無期限に停止します。
通信フローを理解する
TCP ソケットは 1 対 1 の関係を維持しません。異なるエンドポイントでの呼び出しの送信と受信の間。代わりに、プロトコルは通信のルールを定義します。この場合、元のエコー サーバーは、クライアントが接続を閉じるまでサーバーが受信したデータをエコー バックするルールを実装していました。
サーバーの動作が変更されると、ルールは実質的に変更されたことになります。サーバーはデータを受信するだけで、クライアントが接続を閉じるまでデータを破棄します。サーバーがクライアントにデータを送り返すことはありません。
クライアントの動作の調整
変更されたサーバーを操作するには、クライアントはその動作を調整する必要があります。サーバーはデータを積極的に送信しなくなったため、クライアントはデータの受信が接続の完了を示していると想定します。これを容易にするために、クライアントは接続の送信側を閉じて、データの送信が終了したことをサーバーに通知する必要があります。その後、クライアントは複数の recv 呼び出しを実行して、受信データの断片化の可能性を処理できます。
更新されたコード
以下は、サーバーとクライアントの両方の更新されたコードです。 ~の変更されたルールを遵守します通信:
サーバー:
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()
クライアント:
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))
ストリームベースの性質を理解することで、 TCP ソケットとそれに応じた通信ルールの調整により、socket.recv() がデータなしで停止する問題を解決できる可能性があります。送信中です。
以上がサーバーがデータを送り返さないと `socket.recv()` が停止するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。