[英]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_connect
、 sock_accept
、 sock_recv
和sock_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.