📄 form1.cs
字号:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
//套接字与线程的命名空间调用
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace ICMP_App
{
//委托声明 用来在线程中修改窗口控件值
public delegate void SetMyListBox(string mylistvalue);
public delegate string GetMyMessage();
public partial class Form1 : Form
{
//声明委托用来修改列表框中的值
public SetMyListBox dgMyListBox;
//声明用于高级Ping程序与TraceRoute的线程
public Thread advPing,traceRt;
public Form1()
{
InitializeComponent();
}
//发送简单PING命令
private void simpleBtn_Click(object sender, EventArgs e)
{
//若信息未填写完全 报错并退出
if (hostTextBox.Text == "")
{
MessageBox.Show("IP地址不能为空!");
return;
}
//初始化消息数据
byte[] msgData = new byte[1024];
int receive;
//初始化Socket对象 使用Raw套接字进行发送ICMP协议
Socket host = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
//获得远程主机的IP地址
IPHostEntry iphtentry = Dns.GetHostEntry(hostTextBox.Text);
//使用指定的地址和端口号初始化IPEndPoint对象
IPEndPoint ipendp = new IPEndPoint(iphtentry.AddressList[0], 0);
//使用IPEndPoint对象初始化EndPoint对象
EndPoint endp = (EndPoint)ipendp;
//新建一个ICMP对象
ICMP pkt = new ICMP();
//设置ICMP包的类型为询问报文 回送请求
pkt.packType = 0x08;
//ICMP包的代码值为0
pkt.packCode = 0x00;
//校验和为0
pkt.CheckSum = 0;
//填写消息标识符
Buffer.BlockCopy(BitConverter.GetBytes((short)1), 0, pkt.Msg, 0, 2);
//填写消息序列
Buffer.BlockCopy(BitConverter.GetBytes((short)1), 0, pkt.Msg, 2, 2);
//填写包中数据
msgData = Encoding.ASCII.GetBytes("This is a 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;
//设置套接字的超时时间
host.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 3000);
//使用套接字发送ICMP包
host.SendTo(pkt.getBytes(), pktsize, SocketFlags.None, ipendp);
try
{
msgData = new byte[1024];
//接收返回的数据包
receive = host.ReceiveFrom(msgData, ref endp);
}
catch (SocketException)
{
//如果接收失败 则弹出发送失败消息
msgListBox.Items.Add("远程主机没有消息!");
return;
}
//使用获得的返回消息 构造ICMP包
ICMP res = new ICMP(msgData, receive);
//显示ICMP包发送端的位置
msgListBox.Items.Add("Response from: " + endp.ToString());
//显示ICMP包类型
msgListBox.Items.Add("Type: " + res.packType);
//显示ICMP包代码
msgListBox.Items.Add("Code: " + res.packCode);
//获得ICMP包的标识和队列字段
int Idf = BitConverter.ToInt16(res.Msg, 0);
int Seq = BitConverter.ToInt16(res.Msg, 2);
//显示ICMP包的标识和队列字段
msgListBox.Items.Add("Identifer: " + Idf);
msgListBox.Items.Add("Sequence: " + Seq);
//获得ICMP包的数据信息
string strData = Encoding.ASCII.GetString(res.Msg, 4, res.msgSize - 4);
//显示ICMP包的数据信息
msgListBox.Items.Add("Data: "+strData);
//关闭套接字
host.Close();
}
public void advancePing(object ObPingMsg)
{
//获得高级Ping所需的主机地址和数据信息
string[] PingMsg = (string[])ObPingMsg;
string host = PingMsg[0];
string data = PingMsg[1];
//初始化用于显示信息的委托
dgMyListBox = new SetMyListBox(SetMsgBox);
//显示高级PING开始消息
msgListBox.Invoke(dgMyListBox, new object[] { "Pinging "+host });
//初始化Socket对象 使用Raw套接字进行发送ICMP协议
Socket adPingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
//设置Socket对象的超时时间
adPingSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 3000);
//获得远程主机的IP地址
IPHostEntry iphtentry = Dns.GetHostEntry(host);
//使用指定的地址和端口号初始化IPEndPoint对象
IPEndPoint hostIep = new IPEndPoint(iphtentry.AddressList[0], 0);
//使用IPEndPoint对象初始化EndPoint对象
EndPoint hostEp = (EndPoint)hostIep;
//新建一个ICMP对象
ICMP pkt = new ICMP();
int receive,startping,stopping,pingtime;
//初始化ICMP包的序列号
int i = 1;
//设置ICMP包的类型为询问报文 回送请求
pkt.packType = 0x08;
//ICMP包的代码值为0
pkt.packCode = 0x00;
//填写消息标识符
Buffer.BlockCopy(BitConverter.GetBytes(1), 0, pkt.Msg, 0, 2);
//将数据信息转化为字节数组
byte[] msgData = Encoding.ASCII.GetBytes(data);
//填写数据信息
Buffer.BlockCopy(msgData, 0, pkt.Msg, 4, msgData.Length);
//设置ICMP包的大小
pkt.msgSize = msgData.Length + 4;
int pktSize = pkt.msgSize + 4;
//循环发送Ping命令
while (true)
{
//设置校验和为0
pkt.CheckSum = 0;
//填写消息序列
Buffer.BlockCopy(BitConverter.GetBytes(i), 0, pkt.Msg, 2, 2);
//获得消息的校验和
UInt16 checkSum = pkt.getChecksum();
//填写消息的校验和
pkt.CheckSum = checkSum;
//获得Ping命令的开始时间
startping = Environment.TickCount;
//发送ICMP包
adPingSocket.SendTo(pkt.getBytes(), pktSize, SocketFlags.None, hostIep);
try
{
//初始化字节数组 获得发回的ICMP包
msgData = new byte[1024];
receive = adPingSocket.ReceiveFrom(msgData, ref hostEp);
//获得Ping命令的结束时间
stopping = Environment.TickCount;
//得到Ping命令所用的时间
pingtime = stopping - startping;
//显示ICMP包的序列名以及获得该ICMP包所用的时间
msgListBox.Invoke(dgMyListBox, new object[] {"reply from: " + hostEp.ToString() + ", seq: " + i + ", time= " + pingtime + "ms"});
}
catch (SocketException)
{
//如果没有获得返回的数据包 则报错
msgListBox.Invoke(dgMyListBox, new object[] { "主机没有回复消息。" });
}
//序列号加1
i++;
//线程休眠3秒
Thread.Sleep(3000);
}
}
private void advPingBtn_Click(object sender, EventArgs e)
{
if ((hostTextBox.Text == "")||(pktDataTextBox.Text==""))
{
MessageBox.Show("IP地址或数据信息不能为空!");
return;
}
//初始化线程 运行advancePing方法
advPing = new Thread(new ParameterizedThreadStart(advancePing));
//该线程为后台线程
advPing.IsBackground = true;
//将发送ICMP所需消息整合
string[] pingMsg ={hostTextBox.Text,pktDataTextBox.Text};
//作为参数传入线程
advPing.Start(pingMsg);
//设置开始发送按钮不可用
advPingBtn.Enabled = false;
//设置停止发送按钮可用
advPingStopBtn.Enabled = true;
}
//编写委托所用的函数
public void SetMsgBox(string mymessagevalue)
{
//显示消息
msgListBox.Items.Add(mymessagevalue);
}
private void advPingStopBtn_Click(object sender, EventArgs e)
{
//线程终止
advPing.Abort();
//显示线程终止的消息
msgListBox.Invoke(dgMyListBox, new object[] { "Ping Stopped" });
//设置停止按钮不可用
advPingStopBtn.Enabled = false;
//设置高级Ping按钮可用
advPingBtn.Enabled = true;
}
private void traceRtBtn_Click(object sender, EventArgs e)
{
if (hostTextBox.Text == "")
{
MessageBox.Show("IP地址不能为空!");
return;
}
//Trace按钮不可用
traceRtBtn.Enabled = false;
//初始化线程 运行traceRoute方法
traceRt = new Thread(new ParameterizedThreadStart(traceRoute));
//该线程为后台线程
traceRt.IsBackground = true;
//获得主机地址信息
string traceMsg = hostTextBox.Text;
//将主机地址信息作为参数传入
traceRt.Start(traceMsg);
}
public void traceRoute(object ObTraceMsg)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -