第二十八章 Ping28.1 Ping例程概述 Ping例程是W7500EVB使用ICMP协议,查询W7500EVB与需要检查的设备是否处在同一网络。使用前先了解下ICMP协议。 28.2 ICMP协议简介ICMP(Internet Control Message Protocol)是Internet控制报文协议。它是TCP/IP协议簇的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。当遇到IP数据无法访问目标、IP路由器无法按当前的传输速率转发数据包等情况时,会自动发送ICMP消息。 28.3 ICMP报文那么,ICMP 在错误通知和信息查询的时候,网络上交换着怎样的报文呢?先来看一下 RFC(R F C文档中定义了协议的各个方面、协议的用法及协议的管理) 规定的数据包格式和报文内容吧。首先, ICMP 的内容是放在 IP 数据包的数据部分里的。也就是从 ICMP的报文格式来说,ICMP 是 IP 的上层协议。但是,正如 RFC 所记载的,ICMP 是分担了 IP 的一部分功能。所以被认为是与 IP 同层的协议。
图28.3.1 ICMP报文格式 更加详细地看一下数据包的格式吧。看了图3-12-1后应该知道,用来传送 ICMP 报文的 IP 数据包上实际上有不少字段。但是实际上与 ICMP 协议相关的只有 7 个子段。 1)协议;2)源IP 地址; 3)目的 IP 地址;4)生存时间这四个包含在 IP 首部的字段。5)类型;6)代码;7)选项数据;这三个包含在 ICMP数据部分的字段。这里面, 1)协议字段值是 1, 2)和 3)是用来交流 ICMP 报文的地址信息,没有特殊意义。4)与运用 ICMP 时相关。我们使用一个ICMPECHO数据包来探测主机地址是否存活(当然在主机没有被配置为过滤ICMP形式),通过简单的发送一个ICMPECHO(Type 8)数据包到目标主机,如果ICMPECHOReply(ICMPtype0)数据包接收到,说明主机是存活状态。如果没有就可以初步判断主机没有在线或者使用了某些过滤设备过滤了ICMP的REPLY。下面是几种常见的ICMP报文: 1.响应请求 我们日常使用最多的ping,就是响应请求(Type=8)和应答(Type=0),一台主机向一个节点发送一个Type=8的ICMP报文,如果途中没有异常(例如被路由器丢弃、目标不回应ICMP或传输失败),则目标返回Type=0的ICMP报文,说明这台主机存在,更详细的tracert通过计算ICMP报文通过的节点来确定主机与目标之间的网络距离。 2.目标不可到达、源抑制和超时报文 这三种报文的格式是一样的,目标不可到达报文(Type=3)在路由器或主机不能传递数据报时使用,例如我们要连接对方一个不存在的系统端口时,将返回Type=3、Code=3的ICMP报文,它要告诉我们:“嘿,别连接了,我不在家的!”,常见的不可到达类型还有网络不可到达(Code=0)、主机不可到达(Code=1)、协议不可到达(Code=2)等。源抑制则充当一个控制流量的角色,它通知主机减少数据报流量,由于ICMP没有恢复传输的报文,所以只要停止该报文,主机就会逐渐恢复传输速率。最后,无连接方式网络的问题就是数据报会丢失,或者长时间在网络游荡而找不到目标,或者拥塞导致主机在规定时间内无法重组数据报分段,这时就要触发ICMP超时报文的产生。超时报文的代码域有两种取值:Code=0表示传输超时,Code=1表示重组分段超时。 3.时间戳 时间戳请求报文(Type=13)和时间戳应答报文(Type=14)用于测试两台主机之间数据报来回一次的传输时间。传输时,主机填充原始时间戳,接收方收到请求后填充接收时间戳后以Type=14的报文格式返回,发送方计算这个时间差。一些系统不响应这种报文。 ICMP原理: ICMP提供一致易懂的出错报告信息。发送的出错报文返回到发送原数据的设备,因为只有发送设备才是出错报文的逻辑接收者。发送设备随后可根据ICMP报文确定发生错误的类型,并确定如何才能更好地重发失败的数据包。但是ICMP唯一的功能是报告问题而不是纠正错误,纠正错误的任务由发送方完成。 我们在网络中经常会使用到ICMP协议,比如我们经常使用的用于检查网络通不通的Ping命令(Linux和Windows中均有),这个“Ping”的过程实际上就是ICMP协议工作的过程。还有其他的网络命令如跟踪路由的Tracert命令也是基于ICMP协议的。 28.4 Ping命令Ping命令利用ICMP回射请求报文和回射应答报文来测试目标系统是否可达。ICMP回射请求和ICMP回射应答报文是配合工作的。当源主机向目标主机发送了ICMP回射请求数据包后,它期待着目标主机的回答。目标主机在收到一个ICMP回射请求数据包后,它会交换源、目的主机的地址,然后将收到的ICMP回射请求数据包中的数据部分原封不动地封装在自己的ICMP回射应答数据包中,然后发回给发送ICMP回射请求的一方。如果校验正确,发送者便认为目标主机的回射服务正常,即物理连接畅通。 在Windows 9X、Windows 2000等操作系统的Ping命令中,ICMP包中的数据长度默认为32字节,其内容为英文小写字母循环系列(abcdefg…wabcdefghi)。在Cisco路由器、交换机设备中,ICMP包的缺省内容模式是0xabcd。 ping 命令用来在 IP 层次上调查与指定机器是否连通,调查数据包往复需要多少时间。为了实现这个功能,ping 命令使用了两个 ICMP 报文。 执行 ping 后,首先向目标服务器发出回送请求报文。在这个回送请求报文里,除了类型和代码字段,还被追加了标识符和序号字段。标识符和序号字段分别是 16 位的字段。ping 命令在发送回送请求报文时,在这两个字段里填入任意的值。对于标识符,应用程序执行期间送出的所有报文里填入相同的值。对于序号,每送出一个报文数值就增加 1。而且,回送请求的选项数据部分用来装任意数据。这个任意数据用来调整 ping 的交流数据包的大小。 计算机送出的回送请求到达目标服务器后,服务器回答这一请求,向送信方发送回送请求。这个 ICMP 回送回答报文在 IP 层来看,与被送来的回送请求报文基本上一样。不同的只是,源和目标 IP 地址字段被交换了,类型字段里填入了表示回送回答的 0,这两点。也就是,从送信方来看,自己送出的 ICMP 报文从目标服务器那里原样返回了。 图28.4.1 ping 通信顺序图 发送 ICMP 回送请求报文,并填写标识符,序号和数据字段。 发送 ICMP 回送回答报文。并将受到的 ICMP 回送请求报文的标识符,序号和数据字段,原封不动的返回回去。 28.5 Ping例程解析 Ping例程初始化部分和DHCP例程相同,具体分析ping_auto();函数。 [mw_shl_code=applescript,true]1. void ping_auto(uint8 s, uint8 *addr)
2. {
3. uint8 i,ret;
4. int32_t len = 0;
5. uint8 cnt=0;
6. printf("sr:%2x\r\n",getSn_SR(s));
7. for(i = 0; i<=3;i++) //循环ping3次
8. {
9. switch(getSn_SR(s)) //获取socket状态
10. {
11. case SOCK_CLOSED: //socket关闭状态
12. close(s);
13. setSn_PROTO(s,IPPROTO_ICMP); // 设置ICMP 协议
14. ret=socket(s,Sn_MR_IPRAW,3000,0x00);
15. if(ret!=s) //判断ip raw模式socket是否开启
16. { // open the SOCKET with IPRAW mode, if fail then Error
17. printf("SOCK_IPRAW error!\r\n");
18. }
19. /* Check socket register */
20. while(getSn_SR(s)!=SOCK_IPRAW);
21. delay_ms(1000); // 等待 1000ms
22. delay_ms(1000);
23. break;
24. case SOCK_IPRAW: //ip raw模式
25. ping_request(s, addr); //发送Ping请求
26. req++;
27. while(1)
28. {
29. if ( (len = getSn_RX_RSR(s) ) > 0)
30. {
31. ping_reply(s, addr, len); //获取回复信息
32. rep++;
33. break;
34. }
35. else if(cnt > 5)
36. {
37. printf( "Request Time out. \r\n");
38. cnt = 0;
39. break;
40. }
41. else
42. {
43. cnt++;
44. delay_ms(1); // wait 50ms
45. }
46. // 等待2秒,中断失败
47. }
48. break;
49. default:
50. break;
51. }
52. if(req>=3)
53. {
54. #ifdef PING_DEBUG
55. printf("Ping Request = %d, PING_Reply = %d\r\n",req,rep);
56.
57. if(rep == req)
58. printf( "PING SUCCESS\r\n " );
59. else
60. printf( "REPLY_ERROR\r\n " );
61. #endif
62. }
63. }
64. }[/mw_shl_code]
由于ping过程比较快,第7行for循环实现循环ping 3次。通过读取函数getSn_SR()获取socket状态,判断执行哪个模式。第11行如果socket关闭,关闭socket,设置W7500的ICMP协议。第15行判断是否进入IP RAW模式,第25行进入IP RAW模式模式以后发送ping请求,ping次数自加1。29~48行发送ping回复信息,回复次数自加1。3次ping完成以后,判断请求次数与回复次数是否相等,如果相等,回应ping成功信息。 至此 ,Ping例程解析到此结束。编译后烧录打印结果如图28.5.1。
图28.5.1 Ping例程打印结果
|