我在我正在开发的python项目中使用websockets。 websocket在一个线程中运行,并从父线程给出2 queue's。我使用javascript连接到websocket服务器。
我能够通过self.ssi.get(True)
从父线程获取消息并将它们传递给javascript websocket客户端。
但是我无法接收来自客户端的消息。当我使用zaproxy时,我可以看到消息经过。在websocket服务器上,我也能够看到数据包到达接口。 Python不会抛出任何错误,logger.setLevel(logging.DEBUG)
不会显示与我能够看到正在发送邮件的方式相同的邮件。
我一直试图解决这个问题,但我已经没有想法找到问题了,欢迎任何帮助。
Python websocket服务器:
import websockets
import logging
import asyncio
import ssl
class websocket:
def __init__(self,ssi,sso):
self.ssi = ssi
self.sso = sso
logger = logging.getLogger('websockets')
logger.setLevel(logging.DEBUG)
# logger.addHandler(logging.FileHandler('debug.log'))
logger.addHandler(logging.StreamHandler())
sslc = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
sslc.load_cert_chain(
'keys/wss.server.crt',
'keys/wss.server.key')
loop = asyncio.new_event_loop()
wsrv = websockets.serve(
self.handler,
host='0.0.0.0',
port=9000,
ssl=sslc,
loop=loop)
loop.run_until_complete(wsrv)
loop.run_forever()
async def handler(self, wss, path):
consumer_task = asyncio.ensure_future(self.consumerHandler(wss, path))
producer_task = asyncio.ensure_future(self.producerHandler(wss, path))
done, pending = await asyncio.wait(
[consumer_task, producer_task],
return_when=asyncio.FIRST_COMPLETED,)
for task in pending:
task.cancel()
async def producerHandler(self, wss, path):
while True:
msg = await self.producer()
await wss.send(str(msg))
async def consumerHandler(self, wss, path):
async for msg in wss:
await self.consumer(msg)
async def producer(self):
return self.ssi.get(True)
async def consumer(self, msg):
self.sso.put(msg.data)
Javascript客户端:
var ws;
function ws_init() {
ws = new WebSocket("wss://pri.local:9000/");
ws.onopen = function(e) {
output("connected");
};
ws.onmessage = function(e) {
output("i: " + e.data);
};
ws.onclose = function() {
output("disconnect");
};
ws.onerror = function(e) {
output("onerror");
console.log(e)
};
}
function onSubmit() {
var input = document.getElementById("input");
ws.send(input.value);
output("o: " + input.value);
input.value = "";
input.focus();
}
function onCloseClick() {
ws.close();
}
function output(str) {
var log = document.getElementById("log");
var escaped = str.replace(/&/, "&").replace(/</, "<").
replace(/>/, ">").replace(/"/, """); // "
log.innerHTML = escaped + "<br>" + log.innerHTML;
}
答案 0 :(得分:1)
我认为问题在于您正在混合使用queue
库和asyncio.queue
。
queue
是线程安全的,因此是一个很好的线程间通信机制,但它没有异步API,因此当你调用{{1}时你就会阻止websocket线程这可以防止任何其他websocket代码运行。
self.ssi.get(True)
拥有您想要的API(您可以asyncio.queue
),但遗憾的是它不是线程安全的(它设计用于单线程异步应用程序)。
您可以使用await queue.get()
等待阻止loop.run_in_executor
来电。请参阅此处以获取示例https://carlosmaniero.github.io/asyncio-handle-blocking-functions.html