【问题标题】:Multithreaded websocket client does not exit properly多线程 websocket 客户端未正确退出
【发布时间】:2016-11-16 02:12:58
【问题描述】:

我编写了一个多线程 web-socket 客户端类,以便用户的(主)线程不会阻塞 run_forever() 方法调用。代码似乎工作正常,除了最后,当我停止线程时,它不会干净地关闭 web-socket,我的进程也不会退出。我每次都必须做一个kill -9 才能摆脱它。我尝试调用线程的join() 方法以确保主线程等待子线程完成其执行,但这没有帮助。

代码如下所示。你能帮我优雅地退出/停止线程吗?

import thread
import threading
import time
import websocket

class WebSocketClient(threading.Thread):

    def __init__(self, url):
        self.url = url
        threading.Thread.__init__(self)

    def run(self):

        # Running the run_forever() in a seperate thread.
        #websocket.enableTrace(True)
        self.ws = websocket.WebSocketApp(self.url,
                                         on_message = self.on_message,
                                         on_error = self.on_error,
                                         on_close = self.on_close)
        self.ws.on_open = self.on_open
        self.ws.run_forever()

    def send(self, data):

        # Wait till websocket is connected.
        while not self.ws.sock.connected:
            time.sleep(0.25)

        print 'Sending data...', data
        self.ws.send("Hello %s" % data)

    def stop(self):
        print 'Stopping the websocket...'
        self.ws.keep_running = False

    def on_message(self, ws, message):
        print 'Received data...', message

    def on_error(self, ws, error):
        print 'Received error...'
        print error

    def on_close(self, ws):
        print 'Closed the connection...'

    def on_open(self, ws):
        print 'Opened the connection...'

if __name__ == "__main__":

    wsCli = WebSocketClient("ws://localhost:8888/ws")
    wsCli.start()
    wsCli.send('Hello')
    time.sleep(.1)
    wsCli.send('World')
    time.sleep(1)
    wsCli.stop()
    #wsCli.join()
    print 'After closing client...'

【问题讨论】:

  • 在调用wsCli.start()之前尝试设置wsCli.daemon = True
  • 另外,Threaded, non-blocking websocket client 的问题可能对您有价值。
  • 成功了。让它成为守护进程有什么效果?
  • 我查看了run_forever()_app.py 源代码。它包含一个循环,当它创建的WebSocket 连接时通常不会返回。将keep_running 标志设置为False 应该使它脱离循环,任何异常都会发生。我建议您不要设置标志,而是调用self.ws.close() 这样做并且 干净地关闭了sock 连接。请注意,您可能仍应将 daemon 线程属性设置为 True,就像我之前建议的那样,以防万一发生意外并且您的类的 close() 方法没有被调用。
  • 您不需要将self.ws.keep_running 设置为False,这是self.ws.close() 所做的第一件事。无论如何,你的问题现在解决了吗?

标签: python websocket mod-pywebsocket


【解决方案1】:

总结通过我们在 cmets 中的扩展讨论发现的解决方案(并让您有机会接受并投票赞成我的回答。;-)

要解决此问题,您需要在WebSocketClient 类的stop() 方法中调用self.ws.close()而不是,而不仅仅是设置self.ws.keep_running = False。这样 web-socket 就会被彻底关闭。

我还建议您将线程的daemon 属性设置为True,这样当主线程因任何原因终止时线程将自动停止——以防万一发生完全意外的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-22
    • 2018-02-09
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多