ICMP(Internet Control Message Protocal)协议
为了编写本实例,了解ICMP协议是非常必要的。
在互联网络系统中,主机与主机之间的寻址使用IP协议。源地址通过IP地址来同目标进行通信,但有的时候,目标主机也会同源地址进行通信,比如,向源主机报告寻址处理的错误等。对于主机探测、路由维护、路由选择以及流量控制等网络功能来说,通常会用到ICMP协议。ICMP建立在IP协议的基础上,好像它是更高级的协议,而实际上ICMP是IP的一个主要部分,在每一个IP模块它都必须被执行。
当出现下面的某个情况时(仅仅是部分情况),ICMP会有信息被反馈:
寻址无法到达目标
网关对于到来的寻址数据包没有了缓冲能力
网关遇到生存周期为0的报文
事实上,IP协议本身并没有被设计成绝对的可靠,上面的一些控制信息被用来反馈通信环境中出现的问题,但这并不能保证IP包的可靠传输。更高级的协议为了保证绝对可靠传输,通常都加入了新的传输机制。ICMP设计的目的是使网络用户可以检测网络连接的状况以及保证连接的准确性。
实现原理
利用ICMP协议实现路由跟踪的原理如下。
对于ICMP的超时报文,如果网关发现报文的生存周期(TTL)为0,则该数据报必须被抛弃,且网关会向源主机发送超时通知。通过构造ICMP包的IP包头中的TTL字段可以实现这样的发送包。
具体过程是这样:
假设IP将要到达的目标地址需要经过K个路由器(K > 1),则进行下面工作。
1) 构造一个ICMP包,TTL = 1,发送后得到第一个数据路由器的超时报文。
2) 构造第S(S > 16) + (iCheckSum & 0xffff);
iCheckSum += (iCheckSum >> 16);
Array.Copy(BitConverter.GetBytes((ushort)~iCheckSum), 0, ByteSend, 2, 2);
return ByteSend;
}
主函数
以下是主函数Main()的具体实现。
static void Main(string[] args)
{
try
{
if(args.Length== 0)
{
Console.WriteLine("使用方法: tracedemo
return;
}
Socket s= new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
//目标
IPEndPoint ipdest= new IPEndPoint(Dns.Resolve(args[0]).AddressList[0],80);
//源
IPEndPoint ipsrc= new IPEndPoint(Dns.GetHostByName(Dns.GetHostName()).AddressList[0],80);
EndPoint epsrc= (EndPoint)ipsrc;
ICMP ip= new ICMP();
ip.type = ICMPConstants.ICMP_ECHOREQ;
ip.code = 0;
ip.checksum = 0;
ip.id = (ushort)DateTime.Now.Millisecond;
ip.seq = 0;
REQUEST req= new REQUEST();
req.m_icmp= ip;
req.m_data = new Byte[PACKET_SIZE];
//初始化数据
for (int i = 0; i