【问题标题】:Python locks on asyncio socket operationsPython 锁定异步套接字操作
【发布时间】:2020-02-17 11:07:48
【问题描述】:

我试图制作一个连接两个套接字的程序,方法是将一个套接字上读取的数据写入另一个套接字,反之亦然。

import socket as sock
import asyncio

BUFF_SIZE = 4096


async def create_relay(s, port, loop):
    while True:
        s1, _ = await loop.sock_accept(s)  # while awaiting sock_accept no other task is run
        s2 = sock.socket(sock.AF_INET, sock.SOCK_STREAM)
        await loop.sock_connect(s2, ('localhost', port))
        loop.create_task(relay(s1, s2, loop))
        loop.create_task(relay(s2, s1, loop))
        # await asyncio.sleep(1000)        # while awaiting sleep the relay tasks are run

async def relay(s1, s2, loop):
    data = await loop.sock_recv(s1, BUFF_SIZE)
    while data:
        await loop.sock_sendall(s2, data)
        data = await loop.sock_recv(s1, BUFF_SIZE)


def main():
    s = sock.socket(sock.AF_INET, sock.SOCK_STREAM)
    s.bind(('localhost', 9999))
    s.listen()
    loop = asyncio.get_event_loop()
    loop.run_until_complete(create_relay(s, 9990, loop))


if __name__ == '__main__':
    main()

虽然该程序成功设置了套接字,但我实际上无法传输任何消息。调试代码表明程序卡在s1, _ = await loop.sock_accept(s),并且在await另一个连接时不执行任何其他异步代码。但是,如果我在create_relay 循环的末尾添加另一个await,例如await asyncio.sleep(1000),则中继至少部分工作,我可以向一个方向转发消息。

谁能解释一下为什么会发生这些锁定以及如何避免它们?

【问题讨论】:

    标签: python python-3.x sockets python-asyncio


    【解决方案1】:

    谁能解释一下为什么会发生这些锁定以及如何避免它们?

    代码不会使套接字成为非阻塞的。您需要添加:

    s.setblocking(False)
    

    在您创建或获取新套接字的每个地方。

    此外,sock_connectsock_acceptsock_recvsock_sendall 被视为不打算由应用程序代码直接使用的低级 API。相反,您的代码应该使用stream APIs,它提供缓冲等功能,当然还可以自动创建非阻塞套接字。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-23
      • 1970-01-01
      • 2016-03-05
      • 1970-01-01
      相关资源
      最近更新 更多