原生socket使用ICMP协议实现ping单个或多个目标时发生窜包的解决方法
问题描述
原生socket使用ICMP协议实现ping功能,网上代码很多了,我参考的是这本:王艳平,张越.Windows网络与通信程序设计[M].北京人民邮电出版社,2006。
代码逻辑也很清晰,先构造ICMP包,把当前时间填入timestamp字段,调用sendto
发到指定IP,再调用recvfrom
接收,然后用当前时间减去接收到的包的timestamp字段,得到ping的时间。
例子里只发了4个包,没有问题。网络通畅时,也没有问题。
我改了下代码,循环向多个ip轮流发包,然后接收。问题就出现了。
ping的耗时越来越长,开始是1000ms,后面2000ms,3000ms。但从返回包的速度来看,又明显没那么高。
原因分析
反复分析,我又在sendto
和recvfrom
中间加了一段代码:
if (rand() % 2)
{pr.second.ret = TIMEOUT;continue;
}
随机地让程序发出后不收,直接报超时。问题就复现了。在网络好的情况下也能复现问题。
原因其实就是recvfrom
这步漏包了。假设我们发送一组序号为0 1 2 3的ICMP包,发出0之后,如果此时网络较差,recvfrom
没能在超时限制内拿到包,就会返回SOCKET_ERROR
,此时调用WSAGetLastError()
会返回WSAETIMEDOUT
。
之后我们进入下一轮循环,发送1号包,再调用一次recvfrom
取包,而此时收到的包是0号包。
之后我们又进入一轮循环,发送2号包,而此时网络又差了,recvfrom
超时一次。
再一轮循环,发送3号包,再调用一次recvfrom
取包,这时取出了1号包,假设此时2号,3号包其实都已经到了,但因为recvfrom
中间超时2次,现在还在取1号包,所以:
计算出的耗时
= (当前时间-发1号包的时间)
> (2次超时时间)
若超时设置为1秒,则计算出的时间一定大于2秒。
解决方法
所以,在网络较差的环境中,这种sendto
一次,再recvfrom
一次的做法是不正确的。sendto
时的ICMP包应该填入sequence
字段,然后把recvfrom
包进循环,每次recvfrom
得到数据,就进行解析,只有取出的sequence
和当前sequence
相符,才证明中间积压的包已经处理掉了。取最后一次recvfrom
的时间减去最后一次收到的包的timestamp
,得到正确的耗时。
顺带一提,这个问题还有其他解决方法:
- 多进程:用
CreateProcess
调用系统的ping程序,用pipe取得结果。这样开销很大。 - 多线程:开多个线程,每个线程读取自己管理的ip ping的结果,这样情况会好一些,但不能从根本上解决窜包的问题,我没有实验过,不过我猜想如果逻辑还是
sento
一次,recvfrom
一次的话,窜包问题会再现。 - 用第三方dll,比如ICMP.dll,再开多线程调用。这样应该是可以的,系统自带的ping似乎也是调用的ICMP.dll,我没有考证。但系统的ping没有出现窜包的问题,应该是有所规避。这个方法的缺点在于不能跨平台。而我的方法是平台无关的,linux上一样可以用,并且不需要一个ip开一个线程,这样开销太高了。
原生socket使用ICMP协议实现ping单个或多个目标时发生窜包的解决方法相关推荐
- python调用库实现返回ping的时延_python网络作业:使用python的socket库实现ICMP协议的ping...
ICMP ping是您遇到过的最常见的网络扫描类型. 打开命令行提示符或终端并输入ping www.google.com非常容易. 为什么要在python中实现? 很多名牌大学喜欢考试用python的 ...
- 【转】:TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute
TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute 分类: TCP/IP详解学习笔记计算机网络2006-04-20 18:147970人阅读评论(1)收 ...
- ICMP协议的ping和tracert应用
一.实验目的 1.掌握基于ICMP协议的ping和tracert的基本使用方法. 二.实验内容 1.完成ping命令的使用方法和结果演示. 2.完成tracert命令的使用方法和结果演示. 三.实验过 ...
- ping连接linux无法访问目标主机,无法访问目标主机是什么情况【解决方法】
随着近年来IT行业的不断发展,我们的电脑作为IT产品之一,对我们的日常生活有着非常重要的作用,不仅可以利用电脑来进行学习.工作,还可以看视频.听音乐.打游戏.其中,我想,作为电脑运用中最为重要的莫过于 ...
- TCP/IP详解--学习笔记(4)-ICMP协议,ping和Traceroute
1.IMCP协议介绍 前面讲到了,IP协议并不是一个可靠的协议,它不保证数据被送达,那么,自然的,保证数据送达的工作应该由其他的模块来完成.其中一个重要的模块就是ICMP(网络控制报文)协议. 当传送 ...
- tcptracerte参数_TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute【转】
1.IMCP协议介绍 前面讲到了,IP协议并不是一个可靠的协议,它不保证数据被送达,那么,自然的,保证数据送达的工作应该由其他的模块来完成.其中一个重要的模块就是ICMP(网络控制报文)协议. 当传送 ...
- 《TCP/IP详解》学习笔记(四):ICMP 协议、ping 和 Traceroute
ICMP 协议介绍 前面讲到了,IP 协议并不是一个可靠的协议,它不保证数据被成功送达,那么自然的,保证数据送达的工作应该由其他的模块来完 成.其中一个重要的模块就是 ICMP(网络控制报文)协议. ...
- ICMP协议之ping实现
1. 相关ICMP协议概述 这里只讲解与ping有关的ICMP消息类型,主机发送回送消息(Type = 8),被请求主机回送响应消息(Type = 0),基本格式如下: 回送消息[ECHO] 回送响应 ...
- TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute
1.IMCP协议介绍 前面讲到了,IP协议并不是一个可靠的协议,它不保证数据被送达,那么,自然的,保证数据送达的工作应该由其他的模块来完成.其中一个重要的模块就是ICMP(网络控制报文)协议. 当传送 ...
最新文章
- Keil C 中全局变量 extern 的使用
- 最新的ndkr20编译c_史上最优雅的NDK加载pass方案
- iText in Action 2nd5.4节(Adding page events to PdfWriter)读书笔记
- 这可能是由于 CredSSP 加密 Oracle 修正。
- 迫于误解压力,RMS从自由软件基金会与MIT离职
- c语言三个数从小到大排序/输出_我的c语言笔记(三)
- 装13失败后,我决定使用Python为生僻字批量注音
- perl 访问类方法的几种方式
- 和老公去出吃饭,每次我出钱。这样正常吗?
- 工作中遇到的各种问题
- d3js scales深入理解
- 网络相关知识汇总链接
- 阿里云祝顺民:云网络的十年“修路”历程
- 为什么现在的程序员那么卑微?青出于蓝而胜于蓝啊
- 基于单片机的防盗报警监控系统设计(#0401)
- 联想RS550服务器安装Ubuntu16.04
- 【微软资源站】MSDN
- 顶刊TPAMI!目标检测中的不均衡问题综述!
- DaVinci:跟踪器 - 窗口
- 股市 | 股市中的随机事件
热门文章
- 提高MES设备稼动率的管理策略
- 基于MATLAB的简易音乐数字均衡器设计(不采用MATLAB内置函数实现)
- 关于flask入门教程-ajax+echarts简单实现一
- FluentScheduler介绍
- 互联网+时代的“呐喊”:为何软件质量如此重要?
- 期货方法(期货方法很简单 只用MACD)
- oracle jdbc url配置文件,jdbc连接oracle的url配置
- 爱立信面向中国市场推出新一代中频段产品;中石化物探院与浪潮合作提升大数据平台 | 全球TMT...
- media social 指什么_什么是social media?
- 为多孔介质的当量直径_气体在微多孔介质中流动和对流换热研究