python TCPServer地址已经在使用但我关闭了服务器,我使用`allow_reuse_address`

Cla*_*diu 13 python port tcp bind

这是我运行服务器的代码:

class MyRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    #....

PORT = 8089

httpd = SocketServer.TCPServer(("", PORT), MyRequestHandler)
httpd.allow_reuse_address = True

print "Serving forever at port", PORT
try:
    httpd.serve_forever()
except:
    print "Closing the server."
    httpd.server_close()
    raise
Run Code Online (Sandbox Code Playgroud)

然而这就是:

^CClosing the server.
Traceback (most recent call last):
  File "server.py", line 118, in <module>
    self.send_error(400, "Unimplemented GET command: %s" % (self.path,))
  File "/home/claudiu/local/lib/python2.6/SocketServer.py", line 224, in serve_forever
    r, w, e = select.select([self], [], [], poll_interval)
KeyboardInterrupt
(.virtualenv)claudiu@xxx:~/xxx$ python server.py
Traceback (most recent call last):
  File "server.py", line 122, in <module>
    httpd = SocketServer.TCPServer(("", PORT), MyRequestHandler)
  File "/home/claudiu/local/lib/python2.6/SocketServer.py", line 402, in __init__
    self.server_bind()
  File "/home/claudiu/local/lib/python2.6/SocketServer.py", line 413, in server_bind
    self.socket.bind(self.server_address)
  File "<string>", line 1, in bind
socket.error: [Errno 98] Address already in use
Run Code Online (Sandbox Code Playgroud)

为什么?我关闭服务器并设置allow_reuse_address为True ...使用python 2.6.8.

Cla*_*diu 19

感谢其他答案,我想通了.allow_reuse_address应该在课堂上,而不是在实例上:

SocketServer.TCPServer.allow_reuse_address = True
httpd = SocketServer.TCPServer(("", PORT), MyRequestHandler)
Run Code Online (Sandbox Code Playgroud)

我仍然不确定为什么关闭套接字并没有为下次运行服务器释放它.


ece*_*ulm 6

[Err 98] Address already in use是由于套接字是一个事实,.close()但它仍在等待足够的时间来确保远程TCP接收到其连接终止请求的确认(请参阅TIME_WAIT)。默认情况下,如果该端口绑定了套接字,则不允许您绑定套接字,但是可以使用allow_reuse_address(SO_REUSEADDR)覆盖该套接字

尽管可以突变TCPServer.allow_reuse_addr(如该其他答案所建议),但我认为对于您自己的TCPServerwhere allow_reuse_address设置为的子类而言,它更干净True

import SocketServer
import SimpleHTTPServer
import time

class MyRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def do_GET():
        time.sleep(60)
        self.request.sendall("I'm here!")

class ReuseAddrTCPServer(SocketServer.TCPServer):
    allow_reuse_address = True

PORT = 8089

httpd = ReuseAddrTCPServer(("", PORT), MyRequestHandler)
httpd.daemon_threads = True


print "Serving forever at port", PORT
try:
    httpd.serve_forever()
except:
    print "Closing the server."
    httpd.server_close()
    raise
Run Code Online (Sandbox Code Playgroud)

您可以allow_reuse_address在实例本身上使用肯定的设置(而不会弄乱类),但是您需要使用TCPServer(..., bind_and_activate=False),否则套接字将被绑定,然后才有机会更改allow_reuse_address设置。然后,您需要手动调用.server_bind().server_activate()之前serve_forever()

...
httpd = SocketServer.TCPServer(("", PORT), MyRequestHandler, bind_and_activate=False)
httpd.allow_reuse_address = True
httpd.daemon_threads = True
...
httpd.server_bind()
httpd.server_activate()
httpd.serve_forever()
Run Code Online (Sandbox Code Playgroud)