ホームページ > バックエンド開発 > Python チュートリアル > サーバーがデータを送り返さないと `socket.recv()` が停止するのはなぜですか?

サーバーがデータを送り返さないと `socket.recv()` が停止するのはなぜですか?

Patricia Arquette
リリース: 2024-11-22 22:33:26
オリジナル
944 人が閲覧しました

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

ソケットの動作を理解する: データが送信されずに 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 サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート