Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用asyncio add_reader从套接字读取_Python_Sockets_Reader_Python Asyncio - Fatal编程技术网

Python 如何使用asyncio add_reader从套接字读取

Python 如何使用asyncio add_reader从套接字读取,python,sockets,reader,python-asyncio,Python,Sockets,Reader,Python Asyncio,我有以下代码: 导入系统 导入套接字 导入异步 异步def main(目标地址,最大跳数=30,超时=0.5): loop=asyncio.get\u event\u loop() queue=asyncio.queue() 端口=33434 rx=socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_ICMP) rx.settimeout(超时) rx.bind((“”,端口)) def读取器(): 尝试: _,addr=rx.

我有以下代码:

导入系统 导入套接字 导入异步 异步def main(目标地址,最大跳数=30,超时=0.5): loop=asyncio.get\u event\u loop() queue=asyncio.queue() 端口=33434 rx=socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_ICMP) rx.settimeout(超时) rx.bind((“”,端口)) def读取器(): 尝试: _,addr=rx.recvfrom(512) 地址=地址[0] 除socket.timeout外: 地址=无 队列。放置\u nowait(地址) 循环。添加读卡器(接收,读卡器) tx=socket.socket(socket.AF_INET、socket.SOCK_DGRAM、socket.IPPROTO_UDP) 对于范围内的ttl(1,最大跳数+1): tx.setsockopt(socket.SOL_IP,socket.IP_TTL,TTL) 发送到(b“”(目的地址,端口)) addr=等待队列。get() 打印(ttl,地址) 循环。卸下读卡器(rx) 如果名称=“\uuuuu main\uuuuuuuu”: dest_name=sys.argv[1] dest\u addr=socket.gethostbyname(dest\u name) 打印(f“到{dest_name}({dest_addr})”的跟踪路由) asyncio.get_event_loop()。运行_直到完成(main(dest_addr)) 我基本上是在尝试使用asyncio实现跟踪路由

我正在监视套接字文件描述符的读取可用性,并在使用
socket.sendto
方法从设备接收数据时调用
reader
,然后等待队列被填充,然后再进入下一步

但是,我的程序在第一次迭代之后挂起,在第二次
addr=wait queue.get()
上挂起


似乎
读卡器
回调只调用了一次,再也不会调用,因此队列没有被填满,这很奇怪,因为我在
rx
套接字上有0.5s的超时。

回答我自己的问题:

我认为发生的情况是,设备(例如我的前端路由器)没有响应任何东西,因此当文件描述符准备好读取时,我从未收到通知,因此不会调用回调

解决方法是将
队列.get()
包装在
asyncio中。使用超时等待
,这样它就不会永远挂起:

用于范围内的ttl(1,最大跳数+1):
tx.setsockopt(socket.SOL_IP,socket.IP_TTL,TTL)
发送到(b“”(目的地址,端口))
尝试:
addr=wait asyncio.wait_for(queue.get(),超时)
除asyncio.TimeoutError外:
addr=“超时”
打印(ttl,地址)

经过测试,获得了至少7个带有地址的跃点,无法在第一个跃点之后立即复制挂起iteration@RomanPerekhrest你用的是哪个地址?(不知道这有什么关系),我跑了:
sudopython3.6traceroute.py www.google.com
,确实如此hang@RomanPerekhrest怎么可能呢?无论发生什么情况,套接字超时都会触发,因此队列应该在最大0.5sI run
sudo python3~/projects/drafts/networking/traceroute\u emulator.py i.ua
@Newlol后填满。当你有一个有效答案时,你可以回答自己的问题,而不是提供问题中的解决方案。在Ubuntu 18.04上为我工作,但我必须以root用户身份运行脚本,以防止主rx=socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_ICMP)文件/usr/lib/python3.6/socket.py中第11行的
文件“traceroute.py”,第144行的uuu init_usocket.socket.u init_u(self,family,type,proto,fileno)PermissionError:[Errno 1]不允许操作
@V-R Yes,因为创建ICMP数据包需要原始套接字,而原始套接字需要root权限。