2

私はperlTCPサーバー/pythonTCPクライアントを書き込もうとしています、そして私は今そのようなコードを持っています:

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ("127.0.0.1", 9000)
sock.connect(server_address)

try:
    message = unicode('Test')
    sock.sendall(message)
    data = sock.recv(1024)
    print data
finally:
    sock.close()

そして、私のTCPサーバー(perlで書かれている)がの後sendall(message)にではなく、の後にメッセージを受け取っていることに気づきましたclose()。サーバーはエコーサーバーのように機能し、メッセージを受信した後にクライアントにデータを送信します。そして、それはデッドロックを引き起こし、サーバーは決してメッセージを受け取らず、クライアントは決して応答を受け取りません。何が問題になる可能性がありますか?close()そのメッセージがサーバーに届く間に何が起こりますか?

4

1 に答える 1

4

これはサーバーの実装によるものだと推測するのは危険です。エコーサーバーを作成する方法はたくさんあります。

  • EOFまでループ(または非同期コールバック)でバイトを受信します。バイトが受信されると(ループの反復ごとに)、処理やバッファリングなしでそれらをエコーし​​ます。EOFが見つかったら(インバウンドストリームが閉じられたら)、アウトバウンドストリームを閉じます
  • 一度に行を読み取ります(テキストプロトコルであると想定します)。つまり、CR / LF/EOFを探します。行が見つかったら、その行を返します-EOFが見つかった場合(インバウンドストリームが閉じている場合)、アウトバウンドストリームを閉じます
  • EOFに読み取ります; 次に、すべてを返し、アウトバウンドストリームを閉じます

エコーサーバーが最初のアプローチを使用する場合、それはすでに期待どおりに機能するので、それを割り引くことができます。

2番目のアプローチでは、テキストを送信していますが、CR / LFは送信しておらず、クライアントからサーバー(EOF)へのストリームを閉じていないため、サーバーはこの要求に応答しません。そうです、それはデッドロックになります。

これが3番目のアプローチである場合は、アウトバウンドストリームを閉じない限り、デッドロックが発生します。

\nあなたの答えから、それはそれを「修正」するように見えます。このことから、エコーサーバーは回線ベースであると結論付けます。つまり、2つのソリューションと、どのシナリオでも機能する3つ目のソリューションです。

  1. エコーサーバーが行ではなく生データに応答するようにする
  2. 行末マーカーを追加する
  3. クライアントでアウトバウンドストリーム、つまりクライアントからサーバーへのストリームを閉じます(多くのネットワークAPIを使用すると、アウトバウンドストリームとインバウンドストリームを別々に閉じることができます)

さらに、Nagleが無効になっていることを確認してください(多くの場合、NO_DELAYと呼ばれます)-これにより、バイトがクライアントにしばらく留まり、適切なサイズのパケットに構成されるのを待ちます(これは、1と2に適用されますが、3には適用されません。Nagleを有効にすると、遅延を追加しますが、通常はデッドロックは発生しません)。

于 2012-11-19T12:05:14.487 に答える