如何在接收响应时通过 websocket 发送请求

Posted

技术标签:

【中文标题】如何在接收响应时通过 websocket 发送请求【英文标题】:How to send request through websocket while recieving responses 【发布时间】:2020-05-15 17:43:12 【问题描述】:

我正在开展一个项目,该项目涉及通过 Web 套接字从 API 发送请求和获取响应。当我向 API 发送“订阅”请求时,API 将不断地通过 Web 套接字发送响应,我需要在循环中调用 websocket.recv() 来监听响应。如何在收听响应时发送“取消订阅”命令以终止订阅?

...
ws = websocket.create_connection(url, sslopt="cert_reqs": ssl.CERT_NONE)
while True:
 command = input('> ')
 if command == 'subscribe':
    try:
        request = 
            "id": 1,
            "jsonrpc": "2.0",
            "method": "subscribe",
            "params": 
                "token": token,
                "session": session_id,
            
        
        ws.send(json.dumps(request))
        while True:          #I think it should be something else instead of while true     
          result = ws.recv()
          result = json.loads(result)
          print(result)
    except:
        print('No existing token or session')
 elif command == 'unsubscribe':
    try:
        request = 
            "id": 2,
            "jsonrpc": "2.0",
            "method": "unsubscribe",
            "params": 
                "token": token,
                "session": session_id,
            
        
        ws.send(json.dumps(request))
    except:
        print('No existing token or session')
...

我必须使用多线程吗?有没有更好的方法来解决这个问题?谢谢

【问题讨论】:

【参考方案1】:

假设列表 to_send 包含您要在 recv() 期间发送的消息。 您应该做的是使用 socket.settimeout() 并将其设置为较低的值(例如 0.01 秒),然后在循环中使用它。这样,每 0.01 您可以暂停接收,发送 to_send 中的任何内容,然后继续接收新消息。

代码示例:

    your_socket = socket.socket()
    to_send = []
    received_messages = []
    stop = False

    your_socket.settimeout(0.01)
    while not stop:
        try:
            msg = your_socket.recv(1024)
            received_messages.append(msg)
        except socket.error:
            for message in to_send:
                your_socket.send(message)

请注意,此代码每次达到超时时都会使您的程序崩溃(这正是在套接字库中定义超时的方式),因此您必须将代码放在 try 中,除了块。 此外,您不会错过在 except 块中发送的任何消息,因为消息会在网卡上等待您,以便您随时接收。

【讨论】:

感谢您的回答。但是,我想要由用户的命令行输入触发的 to_send 列表。如果我在最后一行使用 your_socket.send(input()) ,程序将暂停以等待用户的输入,而不是继续接收消息。有没有其他办法? @JinpeiHan 在你的情况下,我认为最简单的解决方案是只为输入设置一个线程。

以上是关于如何在接收响应时通过 websocket 发送请求的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 WebSockets 响应 Web 服务请求

等待通过 websocket 的承诺

JavaScript进行WebSocket字节流通讯示例

与 Websockets 同步请求

如何让 Tornado websocket 客户端接收服务器通知?

websocket 发送 响应说明