【问题标题】:Sending many requests in one websocket connection without reconnect在一个 websocket 连接中发送多个请求而无需重新连接
【发布时间】:2019-06-03 17:34:19
【问题描述】:

我的 python 程序运行缓慢,因为任何请求都会重新连接套接字。我想进行一次连接并发送请求,而不需要重新连接

我在文件send_by_socket.py 中的函数,其他一些函数和类调用send_to_socket 用于发送日志消息。现在它可以工作了,但是很慢。原因 - 为任何消息建立新连接。我想要单个连接或轮询以使用它而无需重新连接。如何制作它,可能有很好的源代码示例?

import asyncio
import websockets
from logging import StreamHandler
import json


async def async_send(message):
    async with websockets.connect('wss://****.com/chat') as web_socket:
        await web_socket.send(message)


class WebSocketHandler(StreamHandler):
    def __init__(self):
        StreamHandler.__init__(self)

    def emit(self, record):

        msg = json.dumps({'log': {'message': record.message, 'date': record.asctime, 'level': record.levelname}})
        try:
            asyncio.get_event_loop().run_until_complete(async_send(msg))
        except ConnectionRefusedError:
            pass


def send_to_socket(msg_dict):
    msg = json.dumps(msg_dict)
    try:
        asyncio.get_event_loop().run_until_complete(async_send(msg))
    except ConnectionRefusedError:
        pass

现在程序花费大约 1 - 1.2 秒来处理请求。我试试

con = websockets.connect('wss://****.com/chat')
con.send('some thing')

但有错误AttributeError: 'Connect' object has no attribute 'send'

【问题讨论】:

  • wss 协议适用于 https 你试过使用 ws 吗?它适用于 http ...我建议你使用 http 和 ws 让它工作,然后一旦它的工作转移到 https 和 wss
  • 绝对不能使用 ws。需要 wss。

标签: python-3.x websocket


【解决方案1】:
python
import asyncio
import websockets
from logging import StreamHandler
import json
import time


def singleton(cls):
    instances = {}

    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance


@singleton
class SendToWebSocket:
    """
    Send message in  web-socket, use one connection for sending.
    Try make new connection, if  old is lost.
    """
    __ws = None
    __url = "wss://***.com/chat"

    def __init__(self):
        self.retryTime = 0
        self.retryRepeat = 30
        self.__create_connect()

    @asyncio.coroutine
    def __create_connect(self):
        if (time.time() - self.retryTime) > self.retryRepeat:
            try:
                self.__ws = yield from websockets.connect(self.__url)
                self.retryTime = 0
            except ConnectionRefusedError:
                self.retryTime = time.time()

    def send(self, message):
        t = type(message)
        if t is dict:
            msg = json.dumps(message)
        elif t is str:
            msg = message
        else:
            raise ValueError("Message must be str or dict. Received %s" % type(t))
        if self.__ws is not None:
            try:
                asyncio.get_event_loop().run_until_complete(self.__async_send(msg))
                # print('Send normal')
            except ConnectionRefusedError:
                # print("Can't send")
                # try recreate connect
                self.__create_connect()
        else:
            asyncio.get_event_loop().run_until_complete(self.__create_connect())

    async def __async_send(self, message):
        await self.__ws.send(message)


class WebSocketHandler(StreamHandler):
    """Custom handler for logging library"""

    def __init__(self):
        StreamHandler.__init__(self)
        self.web_socket = SendToWebSocket()

    def emit(self, record):

        msg = json.dumps({'log': {'message': record.message, 'date': record.asctime, 'level': record.levelname}})
        try:
            self.web_socket.send(msg)
        except ConnectionRefusedError:
            pass

【讨论】:

    猜你喜欢
    • 2021-12-29
    • 1970-01-01
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多