问题描述

原生socket使用ICMP协议实现ping功能,网上代码很多了,我参考的是这本:王艳平,张越.Windows网络与通信程序设计[M].北京人民邮电出版社,2006。

代码逻辑也很清晰,先构造ICMP包,把当前时间填入timestamp字段,调用sendto发到指定IP,再调用recvfrom接收,然后用当前时间减去接收到的包的timestamp字段,得到ping的时间。

例子里只发了4个包,没有问题。网络通畅时,也没有问题。

我改了下代码,循环向多个ip轮流发包,然后接收。问题就出现了。

ping的耗时越来越长,开始是1000ms,后面2000ms,3000ms。但从返回包的速度来看,又明显没那么高。

原因分析

反复分析,我又在sendtorecvfrom中间加了一段代码:

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单个或多个目标时发生窜包的解决方法相关推荐

  1. python调用库实现返回ping的时延_python网络作业:使用python的socket库实现ICMP协议的ping...

    ICMP ping是您遇到过的最常见的网络扫描类型. 打开命令行提示符或终端并输入ping www.google.com非常容易. 为什么要在python中实现? 很多名牌大学喜欢考试用python的 ...

  2. 【转】:TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute

    TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute 分类:            TCP/IP详解学习笔记计算机网络2006-04-20 18:147970人阅读评论(1)收 ...

  3. ICMP协议的ping和tracert应用

    一.实验目的 1.掌握基于ICMP协议的ping和tracert的基本使用方法. 二.实验内容 1.完成ping命令的使用方法和结果演示. 2.完成tracert命令的使用方法和结果演示. 三.实验过 ...

  4. ping连接linux无法访问目标主机,无法访问目标主机是什么情况【解决方法】

    随着近年来IT行业的不断发展,我们的电脑作为IT产品之一,对我们的日常生活有着非常重要的作用,不仅可以利用电脑来进行学习.工作,还可以看视频.听音乐.打游戏.其中,我想,作为电脑运用中最为重要的莫过于 ...

  5. TCP/IP详解--学习笔记(4)-ICMP协议,ping和Traceroute

    1.IMCP协议介绍 前面讲到了,IP协议并不是一个可靠的协议,它不保证数据被送达,那么,自然的,保证数据送达的工作应该由其他的模块来完成.其中一个重要的模块就是ICMP(网络控制报文)协议. 当传送 ...

  6. tcptracerte参数_TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute【转】

    1.IMCP协议介绍 前面讲到了,IP协议并不是一个可靠的协议,它不保证数据被送达,那么,自然的,保证数据送达的工作应该由其他的模块来完成.其中一个重要的模块就是ICMP(网络控制报文)协议. 当传送 ...

  7. 《TCP/IP详解》学习笔记(四):ICMP 协议、ping 和 Traceroute

    ICMP 协议介绍 前面讲到了,IP 协议并不是一个可靠的协议,它不保证数据被成功送达,那么自然的,保证数据送达的工作应该由其他的模块来完 成.其中一个重要的模块就是 ICMP(网络控制报文)协议. ...

  8. ICMP协议之ping实现

    1. 相关ICMP协议概述 这里只讲解与ping有关的ICMP消息类型,主机发送回送消息(Type = 8),被请求主机回送响应消息(Type = 0),基本格式如下: 回送消息[ECHO] 回送响应 ...

  9. TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute

    1.IMCP协议介绍 前面讲到了,IP协议并不是一个可靠的协议,它不保证数据被送达,那么,自然的,保证数据送达的工作应该由其他的模块来完成.其中一个重要的模块就是ICMP(网络控制报文)协议. 当传送 ...

最新文章

  1. Keil C 中全局变量 extern 的使用
  2. 最新的ndkr20编译c_史上最优雅的NDK加载pass方案
  3. iText in Action 2nd5.4节(Adding page events to PdfWriter)读书笔记
  4. 这可能是由于 CredSSP 加密 Oracle 修正。
  5. 迫于误解压力,RMS从自由软件基金会与MIT离职
  6. c语言三个数从小到大排序/输出_我的c语言笔记(三)
  7. 装13失败后,我决定使用Python为生僻字批量注音
  8. perl 访问类方法的几种方式
  9. 和老公去出吃饭,每次我出钱。这样正常吗?
  10. 工作中遇到的各种问题
  11. d3js scales深入理解
  12. 网络相关知识汇总链接
  13. 阿里云祝顺民:云网络的十年“修路”历程
  14. 为什么现在的程序员那么卑微?青出于蓝而胜于蓝啊
  15. 基于单片机的防盗报警监控系统设计(#0401)
  16. 联想RS550服务器安装Ubuntu16.04
  17. 【微软资源站】MSDN
  18. 顶刊TPAMI!目标检测中的不均衡问题综述!
  19. DaVinci:跟踪器 - 窗口
  20. 股市 | 股市中的随机事件

热门文章

  1. 提高MES设备稼动率的管理策略
  2. 基于MATLAB的简易音乐数字均衡器设计(不采用MATLAB内置函数实现)
  3. 关于flask入门教程-ajax+echarts简单实现一
  4. FluentScheduler介绍
  5. 互联网+时代的“呐喊”:为何软件质量如此重要?
  6. 期货方法(期货方法很简单 只用MACD)
  7. oracle jdbc url配置文件,jdbc连接oracle的url配置
  8. 爱立信面向中国市场推出新一代中频段产品;中石化物探院与浪潮合作提升大数据平台 | 全球TMT...
  9. media social 指什么_什么是social media?
  10. 为多孔介质的当量直径_气体在微多孔介质中流动和对流换热研究