socketserver
モジュールを使用して単純なソケットサーバーを作成していますが、1つだけ小さなことを除いて、すべて正常に動作しているようです。サーバーをあるポートにバインドしてからserver.allow_reuse_address = True
、カーネルが基になるポートを解放するのを待たずに、同じポートを再利用するように設定しました。ただしserver.allow_reuse_address = True
、サーバーインスタンスの作成後に変数を変更すると機能しませんが、サーバーのカスタムクラスを作成してからその変数をオーバーライドすると、すべてが機能します。
以下は私のコードです。
import socketserver
import sys
class MyTCPRequestehandler(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024)
while self.data:
print('Received {} from {}'.format(self.data.decode().strip(), self.client_address))
self.request.send(self.data.upper())
self.data = self.request.recv(1024)
if __name__ == '__main__':
try:
server = socketserver.TCPServer(('', 12345), MyTCPRequestehandler)
ip, port = server.server_address
server.allow_reuse_address = True
print(server.allow_reuse_address)
print('Server listening on port {}'.format(port))
# server.handle_request()
server.serve_forever()
except KeyboardInterrupt:
sys.exit()
切断した直後にアプリケーションを再実行すると、このエラーが発生します
File "/Documents/PythonPrograms/network-modules/socketServer/simplesocketserver.py", line 16, in <module>
server = socketserver.TCPServer(('', 12345), MyTCPRequestehandler)
File "/spare/ssd/rbhanot/anaconda3/lib/python3.6/socketserver.py", line 453, in __init__
self.server_bind()
File "/spare/ssd/rbhanot/anaconda3/lib/python3.6/socketserver.py", line 467, in server_bind
self.socket.bind(self.server_address)
OSError: [Errno 98] Address already in use
しかし、私が以下のようなことをすれば、すべてがうまくいきます。
class MyTcpServer(socketserver.TCPServer):
allow_reuse_address = True
def __init__(self, address, request_handler_class):
self.address = address
self.request_handler_class = request_handler_class
super().__init__(self.address, self.request_handler_class)
だから私はここで何が欠けていますか?
これは、予想され、文書化された動作です。https://svn.python.org/projects/python/trunk/Lib/SocketServer.pyから:
派生クラスまたはインスタンスによってオーバーライドされる可能性のあるクラス変数:
- タイムアウト
- address_family
- socket_type
- allow_reuse_address
そして、ソースコードをさらに調べると、その理由がわかります。クラスinitはserver_bind()
、を呼び出します。これは、allow_reuse_address
変数をチェックし、setsockopt
必要に応じて実行する関数です。
後で変更した場合、インスタンスの初期化後にそれ以上のチェックは行われません。つまり、変更は何にも影響しません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加