连接寿命更长SocketServer.TCPServer?

2024-10-02 22:35:40 发布

您现在位置:Python中文网/ 问答频道 /正文

如何使TCP服务器正确关闭套接字?在

我编写了一个简单的TCP服务器,将一些信息回送给客户机。现在我想用它本地主机:8088和使用killall停止它,并在我处理代码时随时重新启动。在

但是,我很难让它关闭所有套接字并“释放”地址,所以当我快速地进行一些测试时,修复代码中的某些内容,然后停止(Ctrl+C)并再次启动服务器,我得到socket.error: [Errno 98] Address already in use。在

当我sudo netstat -ntap时,我仍然可以看到一些处于TIME-WAIT状态的127.0.0.1:8088个套接字。所以我只能等到它们“灭绝”。在

我的测试用例:

#!/usr/bin/python
import SocketServer

class MyEchoHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        self.data = self.request.recv(1024).strip()
        # do something smart with the data, but for now, just say hello.
        self.reply = "Content-Type: text/plain\r\n\r\nhello."
        self.request.send(self.reply)
        self.request.close()

def main():
    server = SocketServer.TCPServer((HOST, PORT), MyEchoHandler)
    server.serve_forever()

if __name__ == '__main__':
    HOST, PORT = "localhost", 8088
    main()

我做错什么了?难道self.request.close()还不够吗?在

我正在用Python2.7.3在Debian上尝试这一点,尽管Python2.6也需要支持挤压。在


Tags: 代码self服务器hostclosedataservermain
2条回答

你可以打电话来服务器关闭()但您必须从另一个线程8执行此操作-(在我看来,这是Python TCPServer中的薄弱环节。在

TCP堆栈将端口放入定时等待一段时间(根据您的系统,大约30秒到几分钟)。您可以使用SO\u REUSEADDR socket选项更改该行为。诀窍是在绑定端口之前必须设置该选项。在

如果有原始套接字,则可以:

s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 

SocketServer允许您使用“允许重复使用”地址属性全局设置选项:

^{pr2}$

也可以在创建服务器时执行以下操作:

def main():
    server = SocketServer.TCPServer((HOST, PORT), MyEchoHandler, False)
    server.allow_reuse_address = True
    server.server_bind()
    server.serve_forever()

甚至重写bind方法:

class MyTCPServer(SocketServer.TCPServer):

    def server_bind(self):
        self.allow_reuse_address = True
        super(MyTCPServer, self).server_bind()

这里有3个解决方案,我在我的Windows机器上工作。在

全局设置(1)

#!/usr/bin/python
import SocketServer
import time

SocketServer.allow_reuse_address = True

class MyEchoHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        self.data = self.request.recv(1024).strip()
        # do something smart with the data, but for now, just say hello.
        self.reply = "Content-Type: text/plain\r\n\r\n" + time.asctime()
        self.request.send(self.reply)
        self.request.close()

def main():
    server = SocketServer.TCPServer((HOST, PORT), MyEchoHandler)
    server.serve_forever()

if __name__ == '__main__':
    HOST, PORT = "localhost", 8088
    main()

(2)就地设置

#!/usr/bin/python
import SocketServer
import time

class MyEchoHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        self.data = self.request.recv(1024).strip()
        # do something smart with the data, but for now, just say hello.
        self.reply = "Content-Type: text/plain\r\n\r\n" + time.asctime()
        self.request.send(self.reply)
        self.request.close()

def main():
    server = SocketServer.TCPServer((HOST, PORT), MyEchoHandler, False)
    server.allow_reuse_address = True
    server.server_bind()
    server.server_activate()
    server.serve_forever()

if __name__ == '__main__':
    HOST, PORT = "localhost", 8088
    main()

(3)继承

#!/usr/bin/python
import SocketServer
import time

class MyEchoHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        self.data = self.request.recv(1024).strip()
        # do something smart with the data, but for now, just say hello.
        self.reply = "Content-Type: text/plain\r\n\r\n" + time.asctime()
        self.request.send(self.reply)
        self.request.close()

class MyTCPServer(SocketServer.TCPServer):

    def server_bind(self):
        self.allow_reuse_address = True
        SocketServer.TCPServer.server_bind(self)

def main():
    server = MyTCPServer((HOST, PORT), MyEchoHandler)
    server.serve_forever()

if __name__ == '__main__':
    HOST, PORT = "localhost", 8088
    main()

相关问题 更多 >