【问题标题】:How can I have socket connection and a websocket connection in same client?如何在同一个客户端中拥有套接字连接和 websocket 连接?
【发布时间】:2021-03-11 21:24:06
【问题描述】:

我正在尝试让套接字服务器与 websocket 服务器通信。但我无法让它工作。

首先,我开始使用套接字连接到在 localhost 端口 40404 上运行的服务器。

然后我在 localhost 端口 1236 上启动一个 websocket 服务器。

我有两个异步函数附加到一个事件循环:

监听来自套接字服务器的传入消息并将它们打印到终端。

另一个监听传入的消息到 websocket 服务器并将它们发送到套接字服务器。

我有一个连接到 websocket 服务器的 Javascript 客户端。

当我运行我的代码时,我得到了与套接字服务器的连接,并得到了来自该端的一些响应。但是没有启动 websocket 服务器。

我没有收到任何错误。

我做错了什么?

这是代码:

import socket
import asyncio
import websockets

#Gets any responses from the external socket server
async def get_resp():
    while True:
        resp = s.recv(5000).decode()
        print(resp)
        await asyncio.sleep(1)
 
#Gets any responses from the external websocket server and send it to socket server
async def listen_for_websocket(websocket, path):
    for message in websocket:
        json_obj = json.loads(message)
        print(json_obj["Message"])

        #The message from the JS client is in json format
        message = json_obj["Message"]
        message = message + '\n'
        message = message.encode()

        #Foreward the message to the socket server
        s.send(message)

        #Send a response back to the websocket
        await websocket.send('{"Message":"Thanks for your message"}')

loop = asyncio.get_event_loop()

try:
    #Start up connection with external socket server
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    #Stuf needed by the socket server
    s.connect(('localhost',40404))
    s.send(b'version [["0.1.4"],{}]\n')
    s.send(b'name [["Python"],{}]\n')

    #Starts connection to websocket
    start_server = websockets.serve(listen_for_websocket,'localhost',1236)

    asyncio.ensure_future(get_resp())
    loop.run_until_complete(start_server)
    loop.run_forever()

【问题讨论】:

    标签: python sockets websocket python-asyncio


    【解决方案1】:

    您与套接字服务器的连接不是异步的。阻止对 recv 的调用会停止事件循环并阻止 websockets 部分正常运行。

    您应该调用asyncio.open_connection,而不是直接调用socket.socket 并使用套接字。例如(未经测试):

    async def get_resp(reader):
        while True:
            resp = await reader.read(5000)
            if resp == b'':
                break
            print(resp.decode())
    
    async def listen_for_websocket(websocket, path, writer):
        async for message in websocket:
            json_obj = json.loads(message)
            message = json_obj["Message"] + '\n'
            writer.send(message.encode())
            await websocket.send('{"Message":"Thanks for your message"}')
    
    async def main():
        reader, writer = await asyncio.open_connection('localhost', 40404)
        writer.write(b'version [["0.1.4"],{}]\n')
        writer.write(b'name [["Python"],{}]\n')
        await websockets.serve(
            lambda w, p: listen_for_websocket(w, p, writer),
            'localhost', 1236
        )
        # waits as long as the server is up
        await get_resp(reader)
    
    asyncio.run(main())
    

    【讨论】:

    • 谢谢,现在它可以工作了。唯一的问题是,websocket 对象不再是可迭代的。我得到 TypeError: 'WebSocketServerProtocol' object is not iterable on line 8. 为什么会这样?
    • @Kresten 这听起来很奇怪,因为我没有修改那部分代码。您能否将您正在使用的完整代码发布在 pastebin 或类似工具上?
    • pastebin.com/kf6apgtZ我可能忽略了一些东西。
    • 只需要 async 在 for 前面。现在它的工作。
    • 我很难理解为什么我不需要启动 eventloop 甚至不需要创建 eventlook 对象。你能解释一下吗?
    猜你喜欢
    • 1970-01-01
    • 2015-02-08
    • 2014-05-28
    • 2019-11-19
    • 2015-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    相关资源
    最近更新 更多