[英]Python 3 Threaded websockets server
I'm building a Websocket server application in python 3. I'm using this implementation: https://websockets.readthedocs.io/我正在 python 3 中构建一个 Websocket 服务器应用程序。我正在使用这个实现: https ://websockets.readthedocs.io/
Basically I want to manage multiple client.基本上我想管理多个客户。 Also I want to send data from 2 different thread (one for GPS + one for IMU) GPS thread is refreshed 1Hz, while IMU thread is refresh at 25Hz
另外我想从 2 个不同的线程发送数据(一个用于 GPS + 一个用于 IMU)GPS 线程以 1Hz 刷新,而 IMU 线程以 25Hz 刷新
My problem is in MSGWorker.sendData method: as soon as I uncomment the line @asyncio.coroutine and yield from websocket.send('{"GPS": "%s"}' % data) the whole method does nothing (no print("Send data: foo") in terminal)我的问题出在 MSGWorker.sendData 方法中:一旦我取消注释行 @asyncio.coroutine 并从 websocket.send('{"GPS": "%s"}' % data) 产生,整个方法什么都不做(不打印(“发送数据:foo”)在终端)
However with these two line commented my code works as I expect except that I send nothing through the websocket.但是,通过这两行注释,我的代码可以按预期工作,只是我没有通过 websocket 发送任何内容。
But, of course, my goal is to send data through the websocket, I just don't understand why it doesn't work ?但是,当然,我的目标是通过 websocket 发送数据,我只是不明白为什么它不起作用? Any idea ?
任何想法 ?
server.py服务器.py
#!/usr/bin/env python3
import signal, sys
sys.path.append('.')
import time
import websockets
import asyncio
import threading
connected = set()
stopFlag = False
class GPSWorker (threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.data = 0
self.lastData = 0
self.inc = 0
# Simulate GPS data
def run(self):
while not stopFlag:
self.data = self.inc
self.inc += 1
time.sleep(1)
def get(self):
if self.lastData is not self.data:
self.lastData = self.data
return self.data
class IMUWorker (threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.data = 0
self.lastData = 0
self.inc = 0
# Simulate IMU data
def run(self):
while not stopFlag:
self.data = self.inc
self.inc += 1
time.sleep(0.04)
def get(self):
if self.lastData is not self.data:
self.lastData = self.data
return self.data
class MSGWorker (threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
while not stopFlag:
data = gpsWorker.get()
if data:
self.sendData('{"GPS": "%s"}' % data)
data = imuWorker.get()
if data:
self.sendData('{"IMU": "%s"}' % data)
time.sleep(0.04)
#@asyncio.coroutine
def sendData(self, data):
for websocket in connected.copy():
print("Sending data: %s" % data)
#yield from websocket.send('{"GPS": "%s"}' % data)
@asyncio.coroutine
def handler(websocket, path):
global connected
connected.add(websocket)
#TODO: handle client disconnection
# i.e connected.remove(websocket)
if __name__ == "__main__":
print('aeroPi server')
gpsWorker = GPSWorker()
imuWorker = IMUWorker()
msgWorker = MSGWorker()
try:
gpsWorker.start()
imuWorker.start()
msgWorker.start()
start_server = websockets.serve(handler, 'localhost', 7700)
loop = asyncio.get_event_loop()
loop.run_until_complete(start_server)
loop.run_forever()
except KeyboardInterrupt:
stopFlag = True
loop.close()
print("Exiting program...")
client.html客户端.html
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
</body>
</html>
<script type="text/javascript">
var ws = new WebSocket("ws://localhost:7700", 'json');
ws.onmessage = function (e) {
var data = JSON.parse(e.data);
console.log(data);
};
</script>
Thanks you for your help谢谢你的帮助
Finally I got it !最后我得到了它 ! It required Python 3.5.1 (while my distro provide only 3.4.3) and some help from Aymeric, the author of the websockets library (thanks to him).
它需要 Python 3.5.1(而我的发行版只提供 3.4.3)和来自 websockets 库的作者 Aymeric 的一些帮助(感谢他)。
#!/usr/bin/env python3
import signal, sys
sys.path.append('.')
import time
import websockets
import asyncio
import threading
stopFlag = False
class GPSWorker (threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.data = 0
self.lastData = 0
self.inc = 0
# Simulate GPS data
def run(self):
while not stopFlag:
self.data = self.inc
self.inc += 1
time.sleep(1)
def get(self):
if self.lastData is not self.data:
self.lastData = self.data
return self.data
class IMUWorker (threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.data = 0
self.lastData = 0
self.inc = 0
# Simulate IMU data
def run(self):
while not stopFlag:
self.data = self.inc
self.inc += 1
time.sleep(0.04)
def get(self):
if self.lastData is not self.data:
self.lastData = self.data
return self.data
class MSGWorker (threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.connected = set()
def run(self):
while not stopFlag:
data = gpsWorker.get()
if data:
self.sendData('{"GPS": "%s"}' % data)
data = imuWorker.get()
if data:
self.sendData('{"IMU": "%s"}' % data)
time.sleep(0.04)
async def handler(self, websocket, path):
self.connected.add(websocket)
try:
await websocket.recv()
except websockets.exceptions.ConnectionClosed:
pass
finally:
self.connected.remove(websocket)
def sendData(self, data):
for websocket in self.connected.copy():
print("Sending data: %s" % data)
coro = websocket.send(data)
future = asyncio.run_coroutine_threadsafe(coro, loop)
if __name__ == "__main__":
print('aeroPi server')
gpsWorker = GPSWorker()
imuWorker = IMUWorker()
msgWorker = MSGWorker()
try:
gpsWorker.start()
imuWorker.start()
msgWorker.start()
ws_server = websockets.serve(msgWorker.handler, '0.0.0.0', 7700)
loop = asyncio.get_event_loop()
loop.run_until_complete(ws_server)
loop.run_forever()
except KeyboardInterrupt:
stopFlag = True
#TODO: close ws server and loop correctely
print("Exiting program...")
Regards, Clément问候,克莱门特
I know this is an old thread but I am trying to mimic the functionality and I figured someone may be willing to lend a hand.我知道这是一个旧线程,但我正在尝试模仿该功能,并且我认为有人可能愿意伸出援手。
I have two CAN busses so I want one thread for each.我有两条 CAN 总线,所以我想要一个线程。 I will later have more threads for a web socket connection and possibly other computational tasks.
稍后我将有更多线程用于 Web 套接字连接和可能的其他计算任务。
The code gets stuck in the infinite while loop when I call run on the can0worker.当我在 can0worker 上调用 run 时,代码卡在了无限的 while 循环中。 I'm not familiar enough with python multithreading to know how to fix it.
我对 python 多线程不够熟悉,不知道如何修复它。 I thought that the while loop, because it is on a separate thread, is non-blocking but mine is blocking from the testing that I have done.
我认为while循环,因为它在一个单独的线程上,是非阻塞的,但我的循环阻塞了我所做的测试。
class CANWorker (threading.Thread):
def __init__(self, channel_num):
threading.Thread.__init__(self)
self.msg = None
self.lastmsg = None
self.channel_num = channel_num
print("init", self.channel_num)
os.system(f'sudo ifconfig can{channel_num} down')
os.system(f'sudo ip link set can{channel_num} up type can bitrate 2000000 dbitrate 8000000 restart-ms 1000 berr-reporting on fd on')
os.system(f'sudo ifconfig can{channel_num} txqueuelen 65536')
self.can = can.interface.Bus(channel = f'can{channel_num}', bustype = 'socketcan', fd=True)
def run(self):
print("run", self.channel_num)
while not stopFlag:
self.msg = self.can.recv(0.01)
def get(self):
print("get", self.channel_num)
if self.lastmsg is not self.msg:
self.lastmsg = self.msg
return self.msg
Call this within if __name__ == "__main__"
:在
if __name__ == "__main__"
中调用它:
can0worker = CANWorker(0)
can1worker = CANWorker(1)
can0worker.run()
can1worker.run()
Results after running运行后的结果
init 0
init 1
run 0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.