5

SimpleHTTPRequestHandlerを拡張する単純なサーバーを作成しました

サーバーに何も要求せずに開始および停止すると、問題なく同じポートでバックアップを開始できます。

開始すると、netstat は次のようになります。

sam@hersheezy:server$ sudo netstat -na --program | grep 8001
tcp 0 0 0.0.0.0:8001 0.0.0.0:* リッスン 23392/python

リクエストが行われた後、netstat は次のようになります (リクエストが完了した後でも)。

sam@hersheezy:server$ sudo netstat -na --program | grep 8001
tcp 0 0 0.0.0.0:8001 0.0.0.0:* リッスン 23392/python    
tcp 0 0 127.0.0.1:8001 127.0.0.1:48659 TIME_WAIT -

次に、Cc を使用してサーバーを強制終了すると、netstat は次のようになります (この時点では、ポートが既に使用されているため、サーバーを再起動できません)。

sudo netstat -na --program | grep 8001
tcp 0 0 127.0.0.1:8001 127.0.0.1:48674 TIME_WAIT -

私は明らかに何かを正しく閉じていません。返信を送信する私のコードは次のようになります。

"""
reply is an object that can be json encoded that is written with a response code 200
"""
def send_provider_reply(self, replyobj):
    try:
        str_reply = json.dumps(replyobj)
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        #do we need to send a newline??
        self.wfile.write(str_reply)
    except:
        traceback.print_exc()
        self.send_err(500, 'failed after provider creation')
4

1 に答える 1

6

ソケット オプション SO_LINGER は、ソケットが TIME_WAIT に入ることを防ぎます。しかし、TIME_WAIT には理由があります。それは、古い接続からの残留パケットから保護するためです。したがって、TIME_WAIT のデフォルトの期間は、ネットワーク ラウンドトリップの 2 倍です。そのため、TIME_WAIT で古い接続が見つかるのは正常です。

いくつかのコンテキストを提供するには: サーバー側では、リッスン ソケットを使用して、SO_REUSEADDR ソケット オプションがあります。これにより、リスニング ソケットは TIME_WAIT が終了する前に bind で成功することができます。常に同じポート (ポート 80、443 の Web サーバー) をリッスンする必要があるサーバー プロセスの場合、これは必須です。

サーバーの典型的な python コードには、次のようなものが含まれる場合があります。

...
listener = socket(AF_INET, SOCK_STREAM)
listener.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
listener.bind((HOST, PORT))
listener.listen(32)
...
于 2012-03-05T21:07:45.297 に答える