首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SocketServer在退出时不释放端口

SocketServer在退出时不释放端口
EN

Stack Overflow用户
提问于 2016-07-12 17:05:11
回答 1查看 482关注 0票数 1

我对Python (2.7) socketserver有以下问题:

代码语言:javascript
复制
import wx
import socket
from SocketServer import BaseRequestHandler, ThreadingTCPServer
from threading import Thread
from wx.lib.pubsub import pub
from GUI import GUI

class LogHandler(BaseRequestHandler):
    def handle(self):
        data = self.request.recv(1024)
        wx.CallAfter(pub.sendMessage, 'logmsg', msg=data)
        self.request.close()

class MyTestGUI(GUI):
    def __init__(self):
        super(MyTestGUI, self).__init__(None)
        pub.subscribe(self.AppendLog, 'logmsg')

        self.LogServer = ThreadingTCPServer(('', 10010), LogHandler)
        self.LogServer.allow_reuse_address = True
        self.thd = Thread(target=self.LogServer.serve_forever)
        self.thd.daemon = True
        self.thd.start()

    def AppendLog(self, msg):
        # Append the mesage
        print(msg)

    def AppClose(self, event):
        self.LogServer.shutdown()
        self.LogServer.server_close()
        exit()

if __name__ == '__main__':
    app = wx.App()
    frame = MyTestGUI()
    frame.Show(True)
    app.MainLoop()

此服务器应接收来自设备的消息(在发送消息时关闭套接字)。在第一次运行时,代码运行正常,但在重新启动后,我得到了以下异常:

代码语言:javascript
复制
    self.LogServer = ThreadingTCPServer(('', 10010), LogHandler)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 420, in __init__
    self.server_bind()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 434, in server_bind
    self.socket.bind(self.server_address)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 228, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 48] Address already in use

LogServer.allow_reuse_address = True / False,不会更改任何内容。

EN

回答 1

Stack Overflow用户

发布于 2021-01-25 02:04:22

我在Python3.7.2中使用(非线程) socketserver.TCPServer实例时也遇到了同样的问题。(我在opensuse上使用anaconda,以防万一)

我的解决方案是:

在服务器初始化期间,我将__init__函数的第三个参数设置为false:

  1. 我将__init__标志设置为True,只有在设置了此标志之后,才会调用.server_bind().server_activate()函数。

我认为重要的是在绑定和激活服务器之前设置bind_and_activate标志,因为如果TCPServer初始化期间的bind_and_activate参数为真或未设置,则TCPServer.__init__()将同时调用server_bind()server_activate()函数。在这种情况下,我无法更改.allow_reuse_address标志的值-我可以从print()调用中看到它。

(请注意,下面的代码不起作用,因为其中缺少请求处理程序定义。我也使用超时,但这与问题无关)

代码语言:javascript
复制
def set_up_server_for_one_request(host, port, reqHandler, timeout = 600):
    ''' set up a server for one request. there is timeout as well.
    '''
        
    with socketserver.TCPServer((host, port), reqHandler, \
                                bind_and_activate= False) as serverInstance:  
                
        print('reuse  adress attribute before flag setting: ',\
              serverInstance.socket.getsockopt(socket.SOL_SOCKET,\
                                               socket.SO_REUSEADDR))#print flagVal before setting
        
        serverInstance.allow_reuse_address = True
        
        print('reuse  adress attribute after flag setting: ',\
              serverInstance.socket.getsockopt(socket.SOL_SOCKET, \
                                               socket.SO_REUSEADDR)) #print flagVal after setting
        
        print('server adress: ', serverInstance. server_address)
            
        serverInstance.server_bind()
        
        serverInstance.server_activate()
        
        serverInstance.timeout = timeout    #set server's timeout
        
        serverInstance.handle_request()
        
    print('server finished, and exits')
    
            

if __name__ == '__main__':
    
    set_up_server_for_one_request(host = 'localhost', port = 9998,\
                                  reqHandler = My_EchoRH, timeout = 20)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38324405

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档