Python 如何使用asyncio add_reader从套接字读取
我有以下代码: 导入系统 导入套接字 导入异步 异步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实现跟踪路由 我正在监视套接字文件描述符的读取可用性,并在使用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.
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 runsudo 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权限。