简体   繁体   English

Python 锁定异步套接字操作

[英]Python locks on asyncio socket operations

I tried to make a program that connects two sockets, by writing the data read on one socket to the other and vice versa.我试图制作一个连接两个 sockets 的程序,方法是将一个套接字上读取的数据写入另一个套接字,反之亦然。

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()

While this program successfully sets up the sockets, I can't actually transfer any messages.虽然该程序成功设置了 sockets,但我实际上无法传输任何消息。 Debugging the code has shown that the program gets stuck at s1, _ = await loop.sock_accept(s) and doesn't execute any of the other asynchronous code while await ing another connection.调试代码表明程序卡在s1, _ = await loop.sock_accept(s)并且在await另一个连接时不执行任何其他异步代码。 If however I add another await , like await asyncio.sleep(1000) at the end of the create_relay loop the relay works at least partially and I can forward the messages in one direction.但是,如果我在create_relay循环的末尾添加另一个await ,例如await asyncio.sleep(1000) ,则中继至少部分工作,我可以向一个方向转发消息。

Can somebody explain, why these lock-ups happen and how to avoid them?有人可以解释一下,为什么会发生这些锁定以及如何避免它们?

Can somebody explain, why these lock-ups happen and how to avoid them?有人可以解释一下,为什么会发生这些锁定以及如何避免它们?

The code doesn't make the sockets non-blocking.该代码不会使 sockets 成为非阻塞的。 You need to add:您需要添加:

s.setblocking(False)

in every place where you create or obtain a new socket.在您创建或获取新套接字的每个地方。

Also, sock_connect , sock_accept , sock_recv , and sock_sendall are considered low-level APIs that are not meant to be directly used by application code.此外, sock_connectsock_acceptsock_recvsock_sendall被认为是不打算由应用程序代码直接使用的低级 API。 Instead, your code should use the stream APIs , which provide features such as buffering, and of course automatically create non-blocking sockets.相反,您的代码应该使用stream API ,它提供缓冲等功能,当然还可以自动创建非阻塞 sockets。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM