如何设置允许接收响应ping要求本机ping测试请求的各种icmp数据包

ICMP协议Ping命令的应用
ICMP协议Ping命令的应用
& & ICMP的全称是 Internet Control Message Protocol ,它是TCP/IP协议族的一个子协议,属于网络层协议,用于在IP主机、之间传递控制消息。从技术角度来讲,就是让我们能够判断网络通不通、主机是否可达、路由是否可用等等。
& & & & 在网络中,ICMP协议的应用随处可见,比如我们经常使用的用于检查网络通不通的Ping命令,这个&Ping&的过程实际上就是ICMP协议工作的过程。那么当你&Ping&时,具体的ICMP协议是怎么工作的呢?
& & & & Ping命令利用ICMP回射请求报文和回射应答报文来测试目标是否可达。ICMP回射请求和ICMP回射应答报文是配合工作的。当源主机向目标主机发送了ICMP回射请求数据包后,它期待着目标主机的回答。目标主机在收到一个ICMP回射请求数据包后,它会交换源、目的主机的地址,然后将收到的ICMP回射请求数据包中的数据部分原封不动地封装在自己的ICMP回射应答数据包中,然后发回给发送ICMP回射请求的一方。如果校验正确,发送者便认为目标主机的回射服务正常,也即物理连接畅通。如果校验错误,源主机随后可根据ICMP报文确定发生错误的类型,并确定如何才能更好地重发失败的数据包。注意,ICMP唯一的功能是报告问题而不是纠正错误,纠正错误的任务由源主机完成。
ICMP 重定向
& & & & ICMP虽然不是路由协议,但是有时它也可以指导数据包的流向(使数据流向正确的网关)。ICMP协议通过ICMP重定向数据包达到这个目的。
& & & &如图所示,主机PC要ping路由器R2的loopback 0地址:192.168.3.1,主机将判断出目标属于不同的网段,因此它要将ICMP请求包发往自己的默认网关192.168.1.253(路由器R1的E0接口)。但是,这之前主机PC首先必须发送ARP请求,请求路由器R1的E0(192.168.1.253)的MAC地址。
& & & & 当路由器R1收到此ARP请求包后,它首先用ARP应答包回答主机PC的ARP请求(通知主机PC:路由器R1自己的E0接口的MAC地址)。然后,它(路由器R1)将此ICMP请求转发到路由器R2的E0接口:192.168.1.254(要求路由器R1正确配置了到网络192.168.3.0/24的路由)。此外,路由器R1还要发送一个ICMP重定向消息给主机PC,通知主机PC对于主机PC请求的地址的网关是:192.168.1.254。
& & & & 路由器R2此时会发送一个ARP请求消息请求主机PC的MAC地址,而主机PC会发送ARP应答消息给路由器R2。最后路由器R2通过获得的主机PC的MAC地址信息,将ICMP应答消息发送给主机PC。如果校验正确,就实现了畅通的物理连接。PING分组网间探测 ICMP协议
1、Ping的基础知识
Ping是潜水艇人员的专用术语,表示回应的声纳脉冲,在网络中Ping 是一个十分好用的TCP/IP工具。它主要的功能是用来检测网络的连通情况和分析网络速度。是ICMP的一个重要应用。ping使用了ICMP回送请求与回送回答报文,是应用层直接使用网络层icmp的一个例子。
Ping有好的善的一面也有恶的一面。先说一下善的一面吧。上面已经说过Ping的用途就是用来检测网络的连同情况和分析网络速度,但它是通过什么来显示连通呢?这首先要了解Ping的一些参数和返回信息。
2、Ping命令详解
首先需要打开DOS命令界面,通过点击开始菜单中的“运行”选项,输入“cmd”, 回车即可打开(如下图)。
我们输入 ping /? 例出ping 以下是PING的一些参数(如图):
下面我和大家讲解一下,每个参数意思和使用。
ping [-t] [-a] [-n count] [-l length] [-f] [-i ttl] [-v tos] [-r count] [-s count] [-j computer-list] | [-k computer-list] [-w timeout]destination-list
-t Ping 指定的计算机直到中断。
-a 将地址解析为计算机名。
-n count 发送 count 指定的 ECHO 数据包数。默认值为 4。
-l length 发送包含由 length 指定的数据量的 ECHO 数据包。默认为 32 字节;最大值是65,527。
-f 在数据包中发送&不要分段&标志。数据包就不会被路由上的网关分段。
-i ttl 将&生存时间&字段设置为 ttl 指定的值。
-v tos 将&服务类型&字段设置为 tos 指定的值。
-r count 在&记录路由&字段中记录传出和返回数据包的路由。count 可以指定最少 1 台,最多 9 台计算机。
-s count 指定 count 指定的跃点数的时间戳。
-j computer-list 利用 computer-list 指定的计算机列表路由数据包。连续计算机可以被中间网关分隔(路由稀疏源)IP 允许的最大数量为 9。
-k computer-list 利用 computer-list 指定的计算机列表路由数据包。连续计算机不能被中间网关分隔(路由严格源)IP 允许的最大数量为 9。
-w timeout 指定超时间隔,单位为毫秒。
destination-list 指定要 ping 的远程计算机。
3、怎样使用Ping这命令来测试网络连通呢?
连通问题是由许多原因引起的,如本地配置错误、远程主机协议失效等,当然还包括设备等造成的故障。
首先我们讲一下使用Ping命令的步骤。
使用Ping检查连通性有五个步骤:
1. 使用ipconfig /all观察本地网络设置是否正确,如图;
2. Ping 127.0.0.1,127.0.0.1 回送地址Ping回送地址是为了检查本地的TCP/IP协议有没有设置好;(若请求超时,打开网络连接,你很有可能启用了虚拟wifi。若有无线网卡就把无线网卡关掉,然后本地连接那里(就是有线网卡的那个连接),右键属性,把共享关掉就可以了。)
3. Ping本机IP地址,这样是为了检查本机的IP地址是否设置有误;
4. Ping本网网关或本网IP地址,这样的是为了检查硬件设备是否有问题,也可以检查本机与本地网络连接是否正常;(在非局域网中这一步骤可以忽略)
5. Ping远程IP地址,这主要是检查本网或本机与外部的连接是否正常。
4、如何用Ping命令来判断一条链路好坏?
Ping这个命令除了可以检查网络的连通和检测故障以外,还有一个比较有趣的用途,那就是可以利用它的一些返回数据,来估算你跟某台主机之间的速度是多少字节每秒
我们先来看看它有那些返回数据。
在例子中&bytes=32&表示ICMP报文中有32个字节的测试数据,&time=4ms&是往返时间。 Sent 发送多个秒包、Received 收到多个回应包、Lost 丢弃了多少个Minmum 最小值 、MAXimun 最大值、Average 平均值。所在图上来看,来回只用了4MS 时间,lost =0 即是丢包数为0,网络状态相当良好。 (更详细可以使用-n参数 “ping –n 100 IP地址” ping 100次。查看 Sent Received Lost Minmum MAXimun Average
这些值的变化。)
5、对Ping后返回信息的分析
1.Request timed out
这是大家经常碰到的提示信息,很多文章中说这是对方机器置了过滤ICMP数据包,从上面工作过程来看,这是不完全正确的,至少有下几种情况。
(1)对方已关机,或者网络上根本没有这个地址:比如在上图中主机A中PING 192.168.0.7 ,或者主机B关机了,在主机A中PING 192.168.0.5 都会得到超时的信息。
(2)对方与自己不在同一网段内,通过路由也无法找到对方,但有时对方确实是存在的,当然不存在也是返回超时的信息。
(3)对方确实存在,但设置了ICMP数据包过滤(比如防火墙设置)。
怎样知道对方是存在,还是不存在呢,可以用带参数 -a 的Ping命令探测对方,如果能得到对方的NETBIOS名称,则说明对方是存在的,是有防火墙设置,如果得不到,多半是对方不存在或关机,或不在同一网段内。
(4)错误设置IP地址
正常情况下,一台主机应该有一个网卡,一个IP地址,或多个网卡,多个IP地址(这些地址一定要处于不同的IP子网)。但如果一台电脑的“拨号网络适配器”(相当于一块软网卡)的TCP/IP设置中,设置了一个与网卡IP地址处于同一子网的IP地址,这样,在IP层协议看来,这台主机就有两个不同的接口处于同一网段内。当从这台主机Ping其他的机器时,会存在这样的问题:
A.主机不知道将数据包发到哪个网络接口,因为有两个网络接口都连接在同一网段。
B.主机不知道用哪个地址作为数据包的源地址。因此,从这台主机去Ping其他机器,IP层协议会无法处理,超时后,Ping 就会给出一个“超时无应答”的错误信息提示。但从其他主机Ping这台主机时,请求包从特定的网卡来,ICMP只须简单地将目的、源地址互换,并更改一些标志即可,ICMP应答包能顺利发出,其他主机也就能成功Ping通这台机器了。
2.Destination host Unreachable
(1) 对方与自己不在同一网段内,而自己又未设置默认的路由,比如上例中A机中不设定默认的路由,运行Ping 192.168.0.1.4就会出现“Destination host Unreachable”。
(2)网线出了故障
这里要说明一下“destination host unreachable”和 “time out”的区别,如果所经过的路由器的路由表中具有到达目标的路由,而目标因为其他原因不可到达,这时候会出现“time out”,如果路由表中连到达目标的路由都没有,那就会出现“destination host unreachable”。 3.Bad IP address
这个信息表示您可能没有连接到DNS服务器,所以无法解析这个IP地址,也可能是IP地址不存在。
4.Source quench received
这个信息比较特殊,它出现的机率很少。它表示对方或中途的服务器繁忙无法回应。
5.Unknown host——不知名主机
这种出错信息的意思是,该远程主机的名字不能被域名服务器(DNS)转换成IP地址。故障原因可能是域名服务器有故障,或者其名字不正确,或者网络管理员的系统与远程主机之间的通信线路有故障。
6.No answer——无响应
这种故障说明本地系统有一条通向中心主机的路由,但却接收不到它发给该中心主机的任何信息。故障原因可能是下列之一:中心主机没有工作;本地或中心主机网络配置不正确;本地或中心的路由器没有工作;通信线路有故障;中心主机存在路由选择问题。
7.Ping 127.0.0.1:127.0.0.1是本地循环地址
如果本地址无法Ping通,则表明本地机TCP/IP协议不能正常工作。
8.no rout to host:网卡工作不正常。
9.transmit failed,error code:10043网卡驱动不正常。
10.unknown host name:DNS配置不正确。
最后 介绍一下。使用System.Net.NetworkInformation.Ping来遍历局域网
private void EnumComputers()
string netGate=&100.13.10.&; &//网关
&& for (int i = 1; i &= 255; i++)
&&&& Ping myPing= new Ping();
myPing.PingCompleted += new PingCompletedEventHandler(_myPing_PingCompleted);
&string pingIP =netGate+ i.ToString();
&&&& myPing.SendAsync(pingIP, 1000, null); &//异步方法 发送ICMP回送请求
PRIVATE void _myPing_PingCompleted(object sender, PingCompletedEventArgs e)
if (e.Reply.Status == IPStatus.Success)
Console.WriteLine(e.Reply.Address.ToString()+&|&+Dns.GetHostByAddress(
IPAddress.Parse(e.Reply.Address.ToString())).HostName);
效果评价:速度快,效率高,如果只取在线的IP,不取计算机名,速度会更快。
看过本文的人也看了:
我要留言技术领域:
取消收藏确定要取消收藏吗?
删除图谱提示你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?
删除节点提示无法删除该知识节点,因该节点下仍保存有相关知识内容!
删除节点提示你确定要删除该知识节点吗?查看:9441|回复:8
目的不可达报文 类型:3代码:0至15检验和未使用(全0)收到的IP数据报的一部分,包括IP首部以及数据报数据的前8个字节源端抑制报文 类型:4代码:0检验和未使用(全0)收到的IP数据报的一部分,包括IP首部以及数据报数据的前8个字节超时报文 类型:11代码:0或1检验和未使用(全0)收到的IP数据报的一部分,包括IP首部以及数据报数据的前8个字节参数问题 类型:12代码:0或1检验和指针未使用(全0)收到的IP数据报的一部分,包括IP首部以及数据报数据的前8个字节
改变路由 类型:5代码:0到3检验和目标路由器IP地址收到的IP数据报的一部分,包括IP首部以及数据报数据的前8个字节回送请求和回答 类型:8或0代码:0检验和标识符序号由请求报文发送;由回答报文重复时间戳请求和回答 类型:13或14代码:0检验和标识符序号原始时间戳接收时间戳发送时间戳地址掩码请求和回答 类型:17或18代码:0检验和标识符序号地址掩码路由询问和通告 类型:10代码:0检验和标识符序号
类型:9代码:0检验和地址数地址项目长度寿命路由器地址1地址参考1路由器地址2地址参考2...当发送一份ICMP差错报文时,报文始终包含IP的首部和产生ICMP差错报文的IP数据报的前8个字节。
大家还记得TCP报文的结构么?前面是IP首部,然后是TCP部分。而刚刚说到的前8个字节就包括了TCP的源端口和目的端口啦!这样一来,接受ICMP报文的一方就能根据IP首部和这8个字节来判断出到底是哪个应用程序出错了。(TCP/IP协议栈的分用)。怎么样,这个结构设计得很巧妙吧,可惜不是偶设计滴,:-)。 实验:ICMP协议的分析与实现
[实验目的]
分析ICMP报文,理解ICMP协议在Internet网中的具体应用及其实现原理,深入了解TCP/IP网络的容错控制;学会运用网络套接字Winsock开发网络通信程序。
[实验内容]
使用Visual Studio C++ 6.0和网络接口套接字Socket进行Windows环境下的网络编程,运用原始嵌套字RAW_SOCKET从IP层开始构造整个ICMP报文,通过ICMP协议所提供的回送请求(echo request)和回送应答(echo reply)这两种报文实现检测目的站的可达性与状态。
1.IP报头、ICMP报文的基本描述
IP协议并不能保证绝对的可靠,所以就设计了ICMP协议,进行差错报告.
ICMP 消息使用IP头作为基本控制.
IP头的格式如下:
0& && && && && && && &&&1& && && && && && && && && & 2& && && && && && && && && && & 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
IHL Internet头长
Type of Service = 0
Total Length IP包的总长度
Identification, Flags, Fragment Offset 用于IP包分段
Time to Live IP包的存活时长
Protocol ICMP = 1
Header Checksum 头校验和(检查整个IP报头)
Addresses 发送Echo消息的源地址是发送Echo reply消息的目的地址,相反,发送Echo
消息的目的地址是发送Echo reply消息的源地址.
Echo 或 Echo Reply 消息格式如下:
& & 0& && && && && && && && && &1& && && && && && && && && &&&2& && && && && && && && && & 3
& & 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
& &+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
& &|& &&&Type& && && & |& &&&Code& && & |& && && && && &&&Checksum& && && && & |
& &+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
& &|& && && &&&Identifier& && && && && && && &&&|& && & Sequence Number& && &&&|
& &+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
& &|& && && && && && && && && &&&Data& && && && && && && && && && && && && && && && && && && & |
& &+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
echo消息的类型为8
echo reply 的消息类型为0.
为从TYPE开始到IP包结束的校验和,也就是校验整个ICMP报文
Identifier
如果 code = 0, identifier用来匹配echo和echo reply消息
Sequence Number
如果 code = 0, identifier用来匹配echo和echo reply消息
收到echo 消息必须回应 echo reply 消息. identifier 和 sequence number 可能被发送echo的主机用来匹配返回的echo reply消息.例如: identifier 可能用于类似于TCP或UDP的 port用来标示一个会话, 而sequence number 会在每次发送echo请求后递增. 收到echo的主机或路由器返回同一个值与之匹配
2 数据结构
(1)IP报头格式
//定义IP首部
typedef struct _iphdr{
unsigned char h_ //4 位IP版本号+4位首部长度
//8位服务类型TOS
unsigned short total_ //16位IP包总长度(字节)
//1 6位标识, 用于辅助IP包的拆装,本实验不用,置零
unsigned short frag_and_ //3位标志位+13位偏移位, 也是用于IP包的拆装,本实验不用,置零
//8位IP包生存时间 TTL
//8位协议 (TCP, UDP 或其他), 本实验置ICMP,置为1
uns //16位IP首部校验和,最初置零,等所有包头都填写正确后,计算并替换.
unsigned int sourceIP; //32位源IP地址
unsigned int destIP; //32位目的IP地址
}IP_HEADER;
(2)ICMP报头格式
//定义ICMP首部
typedef struct _icmphdr{
unsigned char i_ //8位类型, 本实验用 8: ECHO 0:ECHO REPLY
unsigned char i_ //8位代码, 本实验置零
unsigned short i_ //16位校验和, 从TYPE开始,直到最后一位用户数据,如果为字节数为奇数则补充一位
unsigned short i_ //识别号(一般用进程号作为识别号), 用于匹配ECHO和ECHO REPLY包
unsigned short i_ //报文序列号, 用于标记ECHO报文顺序
un //时间戳
}ICMP_HEADER;
ICMP协议中的发送、接收ICMP回送请求报文,回送应答报文流程图。
4.VC中网络套接字Winsock编程基础
在VC中进行WINSOCK的API编程开发的时候,需要在项目中使用下面三个文件,否则会出现编译错误。  
1.WINSOCK.H: 这是WINSOCK API的头文件,需要包含在项目中。
2.WSOCK32.LIB: WINSOCK API连接库文件。在使用中,一定要把它作为项目的非缺省的连接库包含到项目文件中去。
3.WINSOCK.DLL: WINSOCK的动态连接库,位于WINDOWS的安装目录下。
几个基本的套接字:
创建套接字——socket()
功能:使用前创建一个新的套接字
格式:SOCKET PASCAL FAR socket(int af,int type,int procotol);
参数:af: 通信发生的区域
type: 要建立的套接字类型
procotol: 使用的特定协议
2、指定本地地址——bind()
功能:将套接字地址与所创建的套接字号联系起来。
格式:int PASCAL FAR bind(SOCKET s,const struct sockaddr FAR * name,int namelen);
参数:s: 是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。
其它:没有错误,bind()返回0,否则SOCKET_ERROR
地址结构说明:
struct sockaddr_in
short sin_//AF_INET
u_short sin_//16位端口号,网络字节顺序
struct in_addr sin_//32位IP地址,网络字节顺序
char sin_zero[8];//保留
建立套接字连接——connect()和accept()
功能:共同完成连接工作
格式:int PASCAL FAR connect(SOCKET s,const struct sockaddr FAR * name,int namelen);
SOCKET PASCAL FAR accept(SOCKET s,struct sockaddr FAR * name,int FAR * addrlen);
参数:同上
4、监听连接——listen()
功能:用于面向连接服务器,表明它愿意接收连接。
格式:int PASCAL FAR listen(SOCKET s, int backlog);
5、数据传输——send()与recv()
功能:数据的发送与接收
格式:int PASCAL FAR send(SOCKET s,const char FAR * buf,int len,int flags);
int PASCAL FAR recv(SOCKET s,const char FAR * buf,int len,int flags);
参数:buf:指向存有传输数据的缓冲区的指针。
6、多路复用——select()
功能:用来检测一个或多个套接字状态。
格式:int PASCAL FAR select(int nfds,fd_set FAR * readfds,fd_set FAR * writefds,
fd_set FAR * exceptfds,const struct timeval FAR * timeout);
参数:readfds:指向要做读检测的指针
writefds:指向要做写检测的指针
exceptfds:指向要检测是否出错的指针
timeout:最大等待时间
7、关闭套接字——closesocket()
功能:关闭套接字s
格式:BOOL PASCAL FAR closesocket(SOCKET s);
5 部分程序代码
//初始化SOCKET
WSADATA wsaD
iErrorCode = WSAStartup(MAKEWORD(2,2),&wsaData);
CheckSockError(iErrorCode, &WSAStartup&);
sockRaw = socket(AF_INET , SOCK_RAW , IPPROTO_ICMP); //原始套接字
CheckSockError(sockRaw, &socket&);
//设置超时时间
iErrorCode = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));//设置接受延时
CheckSockError(iErrorCode, &SO_RCVTIMEO&);
iErrorCode = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));//设置发送延时
CheckSockError(iErrorCode, &SO_SNDTIMEO&);
//获得目标主机IP
memset(&dest,0,sizeof(dest));//初始化dest结构
dest.sin_family = AF_INET; //填充SOCKADDR_IN结构内容
if((dest.sin_addr.s_addr = inet_addr(lpdest)) == INADDR_NONE)
if((hp = gethostbyname(lpdest)) != NULL) //目的主机名字不为空
memcpy(&(dest.sin_addr),hp-&h_addr_list[0],hp-&h_length);
dest.sin_family = hp-&h_
printf(&dest.sin_addr = %s\n&,inet_ntoa(dest.sin_addr));
CheckSockError(SOCKET_ERROR, &gethostbyname()&);
//创建ICMP数据包
datasize += sizeof(ICMP_HEADER); //包长
icmp_data = (char *)malloc(1024); //创建icmp数据报内存空间
recvbuf = (char *)malloc(1024); //接收icmp包缓冲区
if((!icmp_data) || (!recvbuf))
CheckSockError(SOCKET_ERROR, &malloc()&);
memset(icmp_data,0,MAX_PACKET); //初始化icmp_data
FillICMPData(icmp_data,datasize); //填充icmp包
printf(&Pinging %s with %d bytes of data(timeout = %d ms):\n\n&,inet_ntoa(dest.sin_addr),datasize,timeout );
//发送与接收ICMP数据包
memset(recvbuf,0,MAX_PACKET); //初始化接受缓冲区
static int nCount = 0; //设置发送icmp包的次数,一般为4
if(nCount++ ==4)
((ICMP_HEADER*)icmp_data)-&i_cksum = 0; //初设校验和为0
((ICMP_HEADER*)icmp_data)-&timestamp = GetTickCount(); //获得目前时间
((ICMP_HEADER*)icmp_data)-&i_seq = seq_no++; //icmp数据报的序列号
((ICMP_HEADER*)icmp_data)-&i_cksum =
checksum((USHORT*)icmp_data,datasize);//计算校验和
iErrorCode = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest));//发送icmp数据报
if(iErrorCode == SOCKET_ERROR) //错误检查
if(WSAGetLastError() == WSAETIMEDOUT)
printf(&timed out\n&);
CheckSockError(SOCKET_ERROR, &sendto()&);
if(iErrorCode & datasize)
printf(&Wrote %d bytes\n&,iErrorCode);
int fromlen = sizeof(from);//接受icmp包长度
iErrorCode = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,&fromlen);//接受icmp包
if(iErrorCode == SOCKET_ERROR)
if(WSAGetLastError() == WSAETIMEDOUT)
printf(&timed out\n&);
CheckSockError(SOCKET_ERROR, &recvfrom()&);
DecodeICMPHeader(recvbuf,iErrorCode,&from); //分解icmp包头
Sleep(1000); //休眠一段时间
//SOCK错误处理程序
void CheckSockError(int iErrorCode, char *pErrorMsg)
if(iErrorCode==SOCKET_ERROR)
printf(&%s Error:%d\n&, pErrorMsg, GetLastError());
closesocket(sockRaw);
ExitProcess(0);
//填充数据
void FillICMPData(char *icmp_data, int datasize)
ICMP_HEADER *icmp_hdr = NULL;
char *datapart = NULL;
icmp_hdr = (ICMP_HEADER*)icmp_
icmp_hdr-&i_type = ICMP_ECHO; //发送ping
// Request an ICMP echo
icmp_hdr-&i_code = 0; //代码字段为0
icmp_hdr-&i_id = (USHORT)GetCurrentProcessId(); //获得当前进程号
icmp_hdr-&i_cksum = 0;
icmp_hdr-&i_seq = 0; //初始化序列号
datapart = icmp_data + sizeof(ICMP_HEADER); //加上icmp包头
// Place some junk in the buffer
memset(datapart,'E', datasize - sizeof(ICMP_HEADER)); //填充datapart
//计算检验和
USHORT checksum(USHORT *buffer, int size)
unsigned long cksum=0;
while (size & 1)
cksum += *buffer++;
size -= sizeof(USHORT);
cksum += *(UCHAR*)
cksum = (cksum && 16) + (cksum & 0xffff);
cksum += (cksum &&16);
return (USHORT)(~cksum);
//ICMP解包程序
void DecodeICMPHeader(char *buf, int bytes, struct sockaddr_in *from)
IP_HEADER *iphdr = NULL;
ICMP_HEADER *icmphdr = NULL;
iphdr = (IP_HEADER *)
// Number of 32-bit words * 4 = bytes
iphdrlen= sizeof(unsigned long) * (iphdr-&h_lenver & 0xf); //计算ip包头长度
tick = GetTickCount();
if(bytes & iphdrlen + ICMP_MIN) //数据报太短,丢弃
printf(&Too few bytes from %s\n&,inet_ntoa(from-&sin_addr));
icmphdr = (ICMP_HEADER*)(buf + iphdrlen);
if (icmphdr-&i_type != ICMP_ECHOREPLY) //不是回送响应(ping应答),丢弃
printf(&nonecho type %d recvd\n&, icmphdr-&i_type);
// Make sure this is an ICMP reply to something we sent!
if (icmphdr-&i_id != (USHORT)GetCurrentProcessId()) //id号不符合,丢弃
printf(&someone else‘s packet!\n&);
printf(&%d bytes from %s:&, bytes, inet_ntoa(from-&sin_addr)); //输出正在使用的ip地址
printf(& icmp_seq = %d. &, icmphdr-&i_seq); //输出序列号
printf(& time: %d ms&, tick - icmphdr-&timestamp); //输出所用时间
printf(&\n&);
该程序用来检验网络中的一台目标主机是否可达,其功能相当与Windows系统自带的ping命令。例如当程序检验地址为218.199.74.46的目标主机时,可以返回如下信息。
中级工程师
lz我只有一个问题,icmp报文是用来干什么的?
淡泊明志宁静致远
ICMP协议是一种面向连接的协议,用于传输出错报告控制信息。它是一个非常重要的协议,它对于网络安全具有极其重要的意义。
&&它是TCP/IP协议族的一个子协议,属于网络层协议,主要用于在主机与路由器之间传递控制信息,包括报告错误、交换受限控制和状态信息等。当遇到IP数据无法访问目标、IP路由器无法按当前的传输速率转发数据包等情况时,会自动发送ICMP消息。
中级工程师
lz。我是踢馆的:(mars_25): ,icmp就一句话,用来返回查询报文与差错报文的。你觉得如何?
淡泊明志宁静致远
:(pdd_23):
嗯 总结的很好啊
&&学到 啦&&谢谢啦
谢谢版主&&:lol :lol
新手路过 学习了 :loveliness:}

我要回帖

更多关于 wan ping响应 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信