📄 form1.cs
字号:
//初始化用于显示信息的委托
dgMyListBox = new SetMyListBox(SetMsgBox);
//初始化委托
MethodInvoker dgTRBtnTrue = new MethodInvoker(setTRBtnTrue);
//获得主机地址信息
string hostip = (string)ObTraceMsg;
//初始化消息数据
byte[] msgData = new byte[1024];
int receive, starttime, stoptime;
//初始化Socket对象 使用Raw套接字进行发送ICMP协议
Socket hostSock = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
//获得远程主机的IP地址
IPHostEntry hostIPhe = Dns.GetHostEntry(hostip);
//使用指定的地址和端口号初始化IPEndPoint对象
IPEndPoint hostIPep = new IPEndPoint(hostIPhe.AddressList[0], 0);
//使用IPEndPoint对象初始化EndPoint对象
EndPoint hostEndPoint = (EndPoint)hostIPep;
//新建一个ICMP对象
ICMP pkt = new ICMP();
//设置ICMP包的类型为询问报文 回送请求
pkt.packType = 0x08;
//ICMP包的代码值为0
pkt.packCode = 0x00;
//校验和为0
pkt.CheckSum = 0;
//填写消息标识符
Buffer.BlockCopy(BitConverter.GetBytes(1), 0, pkt.Msg, 0, 2);
//填写消息序列
Buffer.BlockCopy(BitConverter.GetBytes(1), 0, pkt.Msg, 2, 2);
//填写数据信息
msgData = Encoding.ASCII.GetBytes("test packet");
Buffer.BlockCopy(msgData, 0, pkt.Msg, 4, msgData.Length);
//设置ICMP包的大小
pkt.msgSize = msgData.Length + 4;
int pktSize = pkt.msgSize + 4;
//获得ICMP包中的校验和
UInt16 checksum = pkt.getChecksum();
//将ICMP包的校验和填入
pkt.CheckSum = checksum;
//设置套接字的超时时间
hostSock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 3000);
//初始化错误消息计数器
int wrongcount = 0;
//最多经过50个路由器
for (int i = 1; i < 50; i++)
{
//改变IP包的TTL值 使其发回一个超时包
hostSock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, i);
//获得数据包的发送时间
starttime = Environment.TickCount;
//发送数据包
hostSock.SendTo(pkt.getBytes(), pktSize, SocketFlags.None, hostIPep);
try
{
//获得返回的消息
msgData = new byte[1024];
receive = hostSock.ReceiveFrom(msgData, ref hostEndPoint);
//获得数据包的接收时间
stoptime = Environment.TickCount;
//使用返回消息初始化ICMP对象
ICMP res = new ICMP(msgData, receive);
int dTime;
//获得从发送数据包到接收包所用的时间
dTime = stoptime - starttime;
//如果数据包类型为超时类型
if (res.packType == 11)
//显示这一跳所经过的路由器地址
msgListBox.Invoke(dgMyListBox, new object[] { "hop " + i + " :response from " + hostEndPoint.ToString() + ", " + dTime + " ms"});
//如果数据包类型为应答类型 说明数据包已经到达目的地
if (res.packType == 0)
{
//显示数据包已经到达目的地
msgListBox.Invoke(dgMyListBox, new object[] {hostEndPoint.ToString() + " reached in " + i + " hops, " + dTime + " ms" });
break;
}
//出错消息计数器置0
wrongcount = 0;
}
catch (SocketException)
{
//如果没有受到返回的消息 显示错误信息
msgListBox.Invoke(dgMyListBox, new object[] {"hop " + i + " : No response from remote host" });
//出错消息计数器加1
wrongcount++;
//如果出错信息到达5条
if (wrongcount == 5)
{
//显示连接远程机器失败
msgListBox.Invoke(dgMyListBox, new object[] { "连接到远端主机失败"});
break;
}
}
}
//关闭套接字
hostSock.Close();
//设置TraceRoute按钮为可用
BeginInvoke(dgTRBtnTrue);
}
public void setTRBtnTrue()
{
//设置TraceRoute按钮可用
traceRtBtn.Enabled = true;
}
//寻找子网掩码
private void findMaskBtn_Click(object sender, EventArgs e)
{
//初始化消息数据
byte[] msgData = new byte[1024];
int receive;
//初始化Socket对象 使用Raw套接字进行发送ICMP协议
Socket hostSock = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
//初始化IPEndPoint对象为广播方式
IPEndPoint hostIep = new IPEndPoint(IPAddress.Broadcast, 0);
//使用IPEndPoint对象初始化EndPoint对象
EndPoint hostEp = (EndPoint)hostIep;
//新建一个ICMP对象
ICMP pkt = new ICMP();
//设置ICMP包的类型为子网掩码请求
pkt.packType = 0x11;
//ICMP包的代码值为0
pkt.packCode = 0x00;
//校验和为0
pkt.CheckSum = 0;
//填写消息标识符
Buffer.BlockCopy(BitConverter.GetBytes(1), 0, pkt.Msg, 0, 2);
//填写消息序列
Buffer.BlockCopy(BitConverter.GetBytes(1), 0, pkt.Msg, 2, 2);
//这些区域全部设为0
Buffer.BlockCopy(BitConverter.GetBytes(0), 0, pkt.Msg, 4, 4);
//设置ICMP包的大小
pkt.msgSize = 8;
int pktSize = pkt.msgSize + 4;
//获得ICMP包中的校验和
UInt16 checkSum = pkt.getChecksum();
//将ICMP包的校验和填入
pkt.CheckSum = checkSum;
//设置套接字的超时时间
hostSock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 30000);
//设置套接字为广播类型
hostSock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
//使用套接字发送ICMP包
hostSock.SendTo(pkt.getBytes(), pktSize, SocketFlags.None, hostIep);
try
{
//使用返回的数据包来初始化字节数组
msgData = new byte[1024];
receive = hostSock.ReceiveFrom(msgData, ref hostEp);
}
catch (SocketException)
{
//如果没有收到返回包 则提示错误
msgListBox.Items.Add("Unable to determine subnet mask for this subnet");
return;
}
//使用返回的字节数组来初始化ICMP包
ICMP res = new ICMP(msgData, receive);
//显示返回的ICMP包的类型
msgListBox.Items.Add("Received an ICMP type " + res.packType + " packet");
//获得子网掩码值
long answerMsg = BitConverter.ToUInt32(res.Msg, 4);
//将子网掩码值转化为IP地址类型
IPAddress hostNetMask = new IPAddress(answerMsg);
//显示子网掩码地址
msgListBox.Items.Add("The subnet mask for this subnet is : " + hostNetMask.ToString());
}
private void clearBtn_Click(object sender, EventArgs e)
{
//清空列表框
msgListBox.Items.Clear();
}
}
//ICMP类
class ICMP
{
//声明ICMP类中的普通数据元素
//ICMP类型
public byte packType;
//ICMP代码
public byte packCode;
//ICMP校验和
public UInt16 CheckSum;
//ICMP消息实际大小
public int msgSize;
//ICMP消息包
public byte[] Msg = new byte[1024];
public ICMP()
{
}
//使用远程设备返回的IP包 创建ICMP对象
public ICMP(byte[] msgdata, int size)
{
//前20个字节为IP包内容 后面开始为ICMP包内容
//获得包的类型信息
packType = msgdata[20];
//获得包的代码信息
packCode = msgdata[21];
//获得包的校验和信息
CheckSum = BitConverter.ToUInt16(msgdata, 22);
//计算出ICMP包的大小
msgSize = size - 24;
//将IP包中ICMP的内容复制到ICMP类中的Msg数组中
Buffer.BlockCopy(msgdata, 24, Msg, 0, msgSize);
}
//将ICMP信息转换为字节数组
public byte[] getBytes()
{
//初始化字节数组的大小
byte[] msgData = new byte[msgSize + 9];
//将包类型信息填入字节数组
Buffer.BlockCopy(BitConverter.GetBytes(packType), 0, msgData, 0, 1);
//将包代码信息填入字节数组
Buffer.BlockCopy(BitConverter.GetBytes(packCode), 0, msgData, 1, 1);
//将包校验和信息填入字节数组
Buffer.BlockCopy(BitConverter.GetBytes(CheckSum), 0, msgData, 2, 2);
//将包中信息填入字节数组
Buffer.BlockCopy(Msg, 0, msgData, 4, msgSize);
//将组装好的字节数组返回
return msgData;
}
//计算校验和方法
public UInt16 getChecksum()
{
UInt32 chksum = 0;
//将ICMP包转化为数组
byte[] msgData = getBytes();
//获得包的大小
int packsize = msgSize + 8;
int index = 0;
//计算校验和算法
while (index < packsize)
{
chksum += Convert.ToUInt32(BitConverter.ToUInt16(msgData, index));
index += 2;
}
chksum = (chksum >> 16) + (chksum & 0xffff);
chksum += (chksum >> 16);
//返回校验和为16位的无符号整型值
return (UInt16)(~chksum);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -