ICMP差错报告报文

ICMP(Internet Control Message Protocol)是Internet控制报文协议。它是TCP/IP协议族的一个子协议。它允许主机或路由器报告差错情况和提供有关异常的报告。
ICMP报文作为IP层数据包的数据,加上数据报的首部,组成IP数据报发送出去。ICMP报文主要分为差错报告报文与查询报文两种。
ICMP差错报告报文只能报告差错,不能纠正差错,差错的纠正留给高层协议去做,它根据源IP地址将差错报告报文发送给IP数据报的源发送站点。共有五种差错报告报文:
1.目的不可达(类型号为3):当路由器找不到路由或者主机不能交付IP数据报时,就丢弃IP数据报,路由器或者主机向IP数据报的源站发送“目的不可达”报文。
目的不可达的情况有:主机不可达;网络不可达;协议不可达(IP数据报要交付的协议TCP未运行);端口不可达;IP数据报需要分片,但DF标志已设置为1或源路由选择失败等。
目的不可达报文的应用:如使用“禁止分片”的IP数据报进行路径MTU的探测等。
2.源站抑制(类型号为4):IP没有流量控制机制。路由器和主机的缓冲区有限,如果发送方发送数据的速率过快。将会导致缓冲区产生溢出。这时路由器或主机只能把某些IP数据报丢弃。
源站抑制报文的应用:给IP协议增加了一种流量控制功能。
3.时间超过(类型号为11):可分为两种情况,第一种是TTL=0:当IP数据报通过路由器时,IP首部的TTL字段减一,当路由器发现收到IP数据报的TTL=0时,就丢弃该报文,同时该路由器向源站点发送ICMP超时报文。第二种是分片不能重组:如果组成IP数据报的所有分片未能在规定的时限内达到目的主机,就不能进行分片的重组,则目的主机会丢弃已经收到的分片,并向源站点发送ICMP超时报文。
时间超过报文的应用:Windows下的Tracert命令行工具是一个探测路由的程序,可以探测IP数据报达到目的时所经过的路由,它利用时间超过ICMP报文和IP数据报首部中的TTL值来实现其功能。
4.参数问题(类型号为12):如果路由器或目的主机发现IP数据报首部的某个字段不正确时,就丢弃该数据报并向源站发送ICMP参数问题报文。
5.改变路由(重定向,类型号为5):在特定情况下,当路由器检测到一台机器使用非优化路由的时候,它会向该主机发送一个ICMP重定向报文,请求主机改变路由,路由器也会把初始数据报向它的目的转发。
但是以下几种情况除外:对ICMP差错报告报文不再发送ICMP差错报告报文;对第一个分片的数据报片的所有后续数据报片都不发送发送ICMP差错报告报文;对具有多播地址的数据报都不发送ICMP差错报告报文;对具有特殊地址(如127.0.0.0或0.0.0.0)的数据报不发送ICMP差错报告报文。
ICMP询问报文有两种,分别是回送请求和回答报文与时间戳请求和回答报文。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个Java示例程序,演示如何发送ICMP回送请求报文,接收ICMP报文,并分析该报文: ```java import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class PingExample { public static void main(String[] args) { // 要ping的IP地址或域名 String ipAddress = "127.0.0.1"; try { // 创建一个DatagramSocket对象,用于发送和接收UDP包 DatagramSocket socket = new DatagramSocket(); // 获取目标IP地址的InetAddress对象 InetAddress address = InetAddress.getByName(ipAddress); // 构造ICMP回送请求报文 byte[] buffer = new byte[32]; buffer[0] = 8; // 类型为8表示ICMP回送请求报文 buffer[1] = 0; // 代码为0表示ICMP回送请求报文 buffer[2] = 0; // 校验和的高字节为0 buffer[3] = 0; // 校验和的低字节为0 buffer[4] = 0; // 标识符的高字节为0 buffer[5] = 0; // 标识符的低字节为0 buffer[6] = 0; // 序列号的高字节为0 buffer[7] = 0; // 序列号的低字节为0 // 后面的24个字节可以填充任意数据 // 计算校验和,将其写入报文中 int checksum = calculateChecksum(buffer, buffer.length); buffer[2] = (byte) (checksum >> 8); buffer[3] = (byte) (checksum & 0xFF); // 发送ICMP回送请求报文 DatagramPacket requestPacket = new DatagramPacket(buffer, buffer.length, address, 0); socket.send(requestPacket); // 接收ICMP报文 byte[] receiveBuffer = new byte[1024]; DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length); socket.receive(receivePacket); // 分析收到的ICMP报文 int type = receiveBuffer[0] & 0xFF; int code = receiveBuffer[1] & 0xFF; if (type == 0 && code == 0) { System.out.println("ICMP回送回答报文正常收到"); } else if (type == 3) { System.out.println("收到ICMP差错报告报文,类型为" + code); } else { System.out.println("收到未知的ICMP报文,类型为" + type + ",代码为" + code); } // 关闭socket socket.close(); } catch (IOException e) { e.printStackTrace(); } } /** * 计算校验和 */ public static int calculateChecksum(byte[] buffer, int length) { int sum = 0; int i = 0; while (length > 1) { sum += ((buffer[i] << 8) & 0xFF00) | ((buffer[i + 1]) & 0xFF); length -= 2; i += 2; } if (length > 0) { sum += (buffer[i] << 8) & 0xFF00; } while ((sum >> 16) > 0) { sum = (sum & 0xFFFF) + (sum >> 16); } return ~sum & 0xFFFF; } } ``` 在上面的代码中,我们使用Java的DatagramSocket类发送和接收UDP包,并构造ICMP回送请求报文。我们还实现了一个calculateChecksum方法,用于计算校验和。发送ICMP回送请求报文后,我们接收ICMP报文,并分析该报文的类型和代码。如果收到的是ICMP回送回答报文,则表示ping成功;如果收到的是ICMP差错报告报文,则表示ping失败;如果收到的是未知的ICMP报文,则可能是网络问题。请注意,此代码需要执行ping命令的操作系统支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值