我正在使用来自这里的代码测试UDP冲压。它在Linux上工作,但是在Windows上报告错误。下面是发生错误的代码片段:
while True:
rfds, _, _ = select([0, sockfd], [], []) # sockfd is a socket
if 0 in rfds:
data = sys.stdin.readline()
if not data:
break
sockfd.sendto(data, target)
elif sockfd in rfds:
data, addr = sockfd.recvfrom(1024)
sys.stdout.write(data)和错误信息:
Traceback (most recent call last):
File "udp_punch_client.py", line 64, in <module>
main()
File "udp_punch_client.py", line 50, in main
rfds, _, _ = select([0, sockfd], [], [])
select.error: (10038, '')我知道这个错误与Windows上的select实现有关,每个人都引用如下:
上的文件对象是不可接受的,但是套接字是可以接受的。在Windows上,基础select()函数是由WinSock库提供的,它不处理不来自WinSock的文件描述符。
所以我有两个问题:
0在[0, sockfd]中是什么意思?这是一种常用的技术吗?select只与Windows上的socket一起工作,如何使代码与socket兼容?谢谢。
发布于 2014-03-07 15:27:14
不幸的是,select无法帮助您在一个线程中处理stdin和网络事件,因为select无法在select上处理流。您需要的是一种不阻塞地读取stdin的方法。你可以使用:
stdin的额外线程。这应该很好,也是做这项工作最简单的方法。如果您需要的只是等待I/O事件,那么Python线程支持是很好的。twisted (请参阅注释)提供非阻塞文件I/O,这种方式是最一致的,但它需要使用与您的框架(twisted或gevent)相匹配的样式编写整个应用程序(twisted或gevent,差别不大)。但是,我怀疑twisted包装器不能从stdin在Windows上进行异步输入(非常肯定它们可以在*nix上完成,因为它们可能使用相同的select)。发布于 2014-03-08 07:24:27
正如答案所示,我创建了另一个线程来处理输入流,它可以工作。以下是修改后的代码:
sock_send = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
def send_msg(sock):
while True:
data = sys.stdin.readline()
sock.sendto(data, target)
def recv_msg(sock):
while True:
data, addr = sock.recvfrom(1024)
sys.stdout.write(data)
Thread(target=send_msg, args=(sock_send,)).start()
Thread(target=recv_msg, args=(sockfd,)).start()https://stackoverflow.com/questions/22251809
复制相似问题