Websocket在线程内部的异步循环中立即断开连接

发布于 2025-02-05 06:14:41 字数 2297 浏览 4 评论 0原文

我正在开发一个应用程序,该应用程序使用多个线程用于各种通信渠道。其中之一是Websocket,我正在使用Asyncio循环运行:

class Rotator():
    def __init__(self):
        # some irrelevant stuff here...
        self._readThread = threading.Thread(target=self._ReadThread, daemon=True)
        self._usbThread = threading.Thread(target=self._UsbThread, daemon=True)
        self._webThread = threading.Thread(target=self._WebThread, daemon=True)
        self._socketThread = threading.Thread(target=self._SocketThread, daemon=True)
        self.InitializeRotator()

    def InitializeRotator(self):
        # some more irrelevant stuff here
        self._readThread.start()
        self._usbThread.start()
        self._webThread.start()
        self._socketThread.start()

    # not including _ReadThread() and _UsbThread() as they are irrelevant in this context

    def _WebThread(self): # including _WebThread() as illustration
        handler_object = server.WebHttpRequestHandler
        _httpServer = socketserver.TCPServer(("",self.webPort), handler_object)
        _httpServer.serve_forever()

    async def ws_handler(websocket, path):
        data = await websocket.recv()
        reply = f"Data recieved as:  {data}!"
        await websocket.send(reply)

    def _SocketThread(self):
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        start_server = websockets.serve(self.ws_handler, str(self.DHCPIP), 8000)

        loop.run_until_complete(start_server)
        loop.run_forever()

与此通信的前端JS代码:

    var ws;
    
    function startWebsocket() {
        ws = new WebSocket('ws://192.168.200.76:8000')

        ws.onopen = function(e){
            console.log('Connection established')
            ws.send('Connection established')
        }

        ws.onmessage = function(e){
            console.log('websocket message event:', e)
        }

        ws.onclose = function(){
            // connection closed, discard old websocket and create a new one in 5s
            console.log('Connection lost, will reconnect in 5s...')
            ws = null
            setTimeout(startWebsocket, 5000)
        }
    }

    startWebsocket();

包含前端的网页由_webthread()运行的服务器提供服务。问题在于,建立后的连接正在立即关闭。我假设问题是由异步/线程组合中的某些冲突引起的,因为我单独测试了服务器端代码,并且像魅力一样工作。我在做什么错?

I'm developing an application that uses multiple threads for various communication channels. One of them is websocket for which I'm using asyncio loop to run:

class Rotator():
    def __init__(self):
        # some irrelevant stuff here...
        self._readThread = threading.Thread(target=self._ReadThread, daemon=True)
        self._usbThread = threading.Thread(target=self._UsbThread, daemon=True)
        self._webThread = threading.Thread(target=self._WebThread, daemon=True)
        self._socketThread = threading.Thread(target=self._SocketThread, daemon=True)
        self.InitializeRotator()

    def InitializeRotator(self):
        # some more irrelevant stuff here
        self._readThread.start()
        self._usbThread.start()
        self._webThread.start()
        self._socketThread.start()

    # not including _ReadThread() and _UsbThread() as they are irrelevant in this context

    def _WebThread(self): # including _WebThread() as illustration
        handler_object = server.WebHttpRequestHandler
        _httpServer = socketserver.TCPServer(("",self.webPort), handler_object)
        _httpServer.serve_forever()

    async def ws_handler(websocket, path):
        data = await websocket.recv()
        reply = f"Data recieved as:  {data}!"
        await websocket.send(reply)

    def _SocketThread(self):
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        start_server = websockets.serve(self.ws_handler, str(self.DHCPIP), 8000)

        loop.run_until_complete(start_server)
        loop.run_forever()

The frontend JS code that communicates with this is:

    var ws;
    
    function startWebsocket() {
        ws = new WebSocket('ws://192.168.200.76:8000')

        ws.onopen = function(e){
            console.log('Connection established')
            ws.send('Connection established')
        }

        ws.onmessage = function(e){
            console.log('websocket message event:', e)
        }

        ws.onclose = function(){
            // connection closed, discard old websocket and create a new one in 5s
            console.log('Connection lost, will reconnect in 5s...')
            ws = null
            setTimeout(startWebsocket, 5000)
        }
    }

    startWebsocket();

The web page that contains the frontend is served by the server run by _WebThread(). The issue is that the connection is being closed immediately after being established. I'm assuming the issue is caused by some conflict in the asyncio/thread combination, because I tested the server side code on its own and it worked like a charm. What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浅忆 2025-02-12 06:14:41

我重新创建了您的示例,并设法使用两个更改来修复它:

  1. ws_handler缺少self参数。由于这是一个实例方法,因此实例本身将作为第一个参数传递。实际的Websocket对象将是第二个。

  2. 在WS_HANDLER中,我在true 循环时添加了。我在此处的文档中遵循了 https:// https:// websockets.readthedocs.io/en/stable/intro/tutorial1.html#bootstrap-the-server


最终结果:

    async def ws_handler(self, websocket, path):
        while True:
            data = await websocket.recv()
            reply = f"Data recieved as:  {data}!"
            await websocket.send(reply)

我所做的其他更改是使用8000用作HTTP服务器的端口,Websocket的8001和“ localhost”,而不是192.168.200.76。但是我很确定这无关紧要

I recreated your example and managed to fix it using two changes:

  1. ws_handler is missing the self parameter. Since it's an instance method, the instance itself will be passed as the first parameter. The actual websocket object will be the second one.

  2. in ws_handler I added a while True loop. I followed the example in the docs here https://websockets.readthedocs.io/en/stable/intro/tutorial1.html#bootstrap-the-server

final result:

    async def ws_handler(self, websocket, path):
        while True:
            data = await websocket.recv()
            reply = f"Data recieved as:  {data}!"
            await websocket.send(reply)

Other changed that I made were to use 8000 as a port for the http server, 8001 for the websocket server and 'localhost' instead of 192.168.200.76. But I'm pretty sure that's not relevant

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文