Issue
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?
Solution
I recreated your example and managed to fix it using two changes:
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.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
Answered By - Anton Mihaylov
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.