原生socket套接字实现ICMP协议(原生socket套接字实现ICMP协议)(1)

版权声明:本文为作者原创文章,可以随意转载,但必须在明确位置表明出处!!!

前一篇文章讲了TCP协议,本篇文章我觉得有必要去实现一种协议,让我们更深刻的去理解协议内容,所以本篇文章选择ICMP(Internet Control Message Protocol)Internet控制报文协议,它是一种网络层协议,相信各位都使用过ping命令,监测主机和主机之间能够联通,而ping命令就是使用的ICMP协议,下面我们就用socket实现一个ping程序。

ping命令过程

1.Ping命令加上一个主机地址或者域名

2.等待对方主机应答。

3.统计发送接收次数,是否有丢包。

ICMP不能单独传输,它需要封装在IP数据报里。如下图所示:

原生socket套接字实现ICMP协议(原生socket套接字实现ICMP协议)(2)

发送ICMP数据报需要填充ICMP头部信息,头部 发送的数据部分组成一个ICMP报文。填充头部的意义是设置你想要的结果。ICMP头部占8个字节。类型一个字节,代码一个字节,校验和两个字节,标识符两个字节,序列号两个字节。类型和代码的组合可以表达不同的意义。这里我们会用到类型8代码0;表示的是ECHO请求。当对方主机返回类型为0时,表示ECHO应答。IP首部占20个字节下面给出ICMP头部和IP头部的定义。

ICMP报文类型

原生socket套接字实现ICMP协议(原生socket套接字实现ICMP协议)(3)

ICMP头部定义

原生socket套接字实现ICMP协议(原生socket套接字实现ICMP协议)(4)

下面我们就要填充ICMP头部信息

原生socket套接字实现ICMP协议(原生socket套接字实现ICMP协议)(5)

icmp_hdr->id = (USHORT)GetCurrentProcesId();这里的ID是唯一的标识符,他的作用是从应答中找到属于我发起的请求应答,是什么意思呢,一个网络地址可能同时有多个人去PING一台主机,那么主机返回的数据谁去接受呢?其实就是用ID来决定的,比如A、B两个用户,他们都ping同一台主机,A的ID = 1 B的ID = 2;那么主机返回的时候这个ID值是不会改变的,A判断ID == 1 就表示我返回我要接受的数据,同理B判断ID == 2,就是这个意思。

icmp_hdr->timestamp = GetTickCount();主要是用来记录请求应答的时间,当发送ECHO请求时记录发送时间,当接受到应答数据时,在用GetTickcount()- icmp_hdr->itmestamp这样就能得到请求应答需要多少时间了。

发送ICMP数据使用原始套接字,用sendto(···)函数,函数的接受可以查看MSDN关于本文的所有API函数都可以通过MSDN查看,多查看MSDN对我们提高英文能力,和学习能力都有很好的帮助,学习编程一定要多查看文档,遇到API先看文档,如果不是很明白在去百度,google这样会好一些。

下面是接受到ECHO应答后解析数据的过程:

原生socket套接字实现ICMP协议(原生socket套接字实现ICMP协议)(6)

下面是接受数据:

原生socket套接字实现ICMP协议(原生socket套接字实现ICMP协议)(7)

下面是发送请求数据

原生socket套接字实现ICMP协议(原生socket套接字实现ICMP协议)(8)

okay, 就讲到这里了,各位读者可以自己动手去试试,当然如果你们需要demo的也可以私信我。


欢迎关注我:「爱做饭的老谢」,老谢一直在努力...

,