Python websockets,无法接收消息

时间:2018-02-14 00:20:20

标签: python websocket python-asyncio

我在我正在开发的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(/&/, "&amp;").replace(/</, "&lt;").
        replace(/>/, "&gt;").replace(/"/, "&quot;"); // "
        log.innerHTML = escaped + "<br>" + log.innerHTML;
}

1 个答案:

答案 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