Visual C# Simulate "Tracert" Command

 

using System ;
using System.Drawing ;
using System.Collections ;
using System.ComponentModel ;
using System.Windows.Forms ;
using System.Data ;
using System.Net ;
using System.Net.Sockets ;
namespace WindowsApplication24
{
 /// <summary>
 /// Form1 的摘要说明。
 /// </summary>
 public class Form1 : System.Windows.Forms.Form
 {
  private System.Windows.Forms.Label label1 ;
  private System.Windows.Forms.TextBox textBox1 ;
  private System.Windows.Forms.Button button1 ;
  private System.Windows.Forms.ListBox listBox1 ;
  /// <summary>
  /// 必需的设计器变量。
  /// </summary>
  private System.ComponentModel.Container components = null ;
  public Form1  (   )
  {
   //
   // Windows 窗体设计器支持所必需的
   //
   InitializeComponent  (   )  ;
   //
   // TODO: 在 InitializeComponent 调用后添加任何构造函数代码
   //
  }
  /// <summary>
  /// 清理所有正在使用的资源。
  /// </summary>
  protected override void Dispose  (   bool disposing   )
  {
   if  (   disposing   )
   {
    if   (  components != null  ) 
    {
     components.Dispose  (   )  ;
    }
   }
   base.Dispose  (   disposing   )  ;
  }
  #region Windows Form Designer generated code
  /// <summary>
  /// 设计器支持所需的方法 - 不要使用代码编辑器修改
  /// 此方法的内容。
  /// </summary>
  private void InitializeComponent  (   )
  {
            this.label1 = new System.Windows.Forms.Label();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.button1 = new System.Windows.Forms.Button();
            this.listBox1 = new System.Windows.Forms.ListBox();
            this.SuspendLayout();
            //
            // label1
            //
            this.label1.Location = new System.Drawing.Point(11, 13);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(99, 25);
            this.label1.TabIndex = 0;
            this.label1.Text = "目的地址:";
            //
            // textBox1
            //
            this.textBox1.Location = new System.Drawing.Point(94, 11);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(232, 21);
            this.textBox1.TabIndex = 1;
            //
            // button1
            //
            this.button1.Location = new System.Drawing.Point(340, 9);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(68, 28);
            this.button1.TabIndex = 2;
            this.button1.Text = "Tracert";
            this.button1.Click += new System.EventHandler(this.button1_Click);
            //
            // listBox1
            //
            this.listBox1.BackColor = System.Drawing.SystemColors.WindowText;
            this.listBox1.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.listBox1.ForeColor = System.Drawing.SystemColors.Window;
            this.listBox1.ItemHeight = 12;
            this.listBox1.Location = new System.Drawing.Point(0, 41);
            this.listBox1.Name = "listBox1";
            this.listBox1.Size = new System.Drawing.Size(370, 304);
            this.listBox1.TabIndex = 3;
            //
            // Form1
            //
            this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
            this.ClientSize = new System.Drawing.Size(370, 345);
            this.Controls.Add(this.listBox1);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.label1);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.MaximizeBox = false;
            this.Name = "Form1";
            this.Text = "C#实现Tracert命令";
            this.ResumeLayout(false);
            this.PerformLayout();

  }
  #endregion
  /// <summary>
  /// 应用程序的主入口点。
  /// </summary>
   [STAThread ]
  static void Main  (   ) 
  {
   Application.Run  (  new Form1  (   )   )  ;
  }
  private void button1_Click  (  object sender  , System.EventArgs e  )
  {
   listBox1.Items.Clear  (   )  ;
   //清除Tracert命令的结果显示区
   try
   {
    if  (  textBox1.Text.Length == 0  )
    {
     listBox1.Items.Add  (  "请输入目的地址!"  )  ;
     textBox1.Focus  (   )  ;
     return ;
    }
    Socket s = new Socket  (  AddressFamily.InterNetwork  , SocketType.Raw  , ProtocolType.Icmp  )  ;
    //创建接收和发送ICMP报文的Socket
    IPEndPoint ipDEST = new IPEndPoint  (  Dns.Resolve  (  textBox1.Text  ) .AddressList [ 0 ]   ,30  )  ;
    // 设定服务器端30端口号对应的网络结点
    IPEndPoint ipSRC = new IPEndPoint  (  Dns.GetHostByName  (  Dns.GetHostName  (   )   ) .AddressList [ 0 ]   ,30  )  ;
    EndPoint epSRC =   (  EndPoint  )  ipSRC ; 
    int DataSize = 4 ; // ICMP报文中的“数据”长度“ ;
    int PacketSize = DataSize + 8 ;//总报文长度
    const int ICMP_ECHO = 8 ;
    IcmpPacket packet = new IcmpPacket  (  ICMP_ECHO  , 0  , 0  , 45  , 0  , DataSize  )  ;
           Byte  [ ]  Buffer = new Byte [ PacketSize  ]  ;
    int index = packet.CountByte  (  Buffer  )  ;
    if  (   index != PacketSize  )
    {
     listBox1.Items.Add  (  "报文出现问题!"  )  ;
     return  ;
    }
    int cksum_buffer_length =  (  int  )  Math.Ceiling  (   (   (  Double  )  index  )  / 2  )  ;
    UInt16  [ ]  cksum_buffer = new UInt16 [ cksum_buffer_length ]  ;
    int icmp_header_buffer_index = 0 ;
    for  (   int i = 0 ; i < cksum_buffer_length ; i++   ) 
    {
     //将两个byte转化为一个UInt16
     cksum_buffer [ i ]  = BitConverter.ToUInt16  (  Buffer  , icmp_header_buffer_index  )  ;
     icmp_header_buffer_index += 2 ;
    }
    //将校验和保存至报文里
    packet.CheckSum = IcmpPacket.SumOfCheck  (  cksum_buffer  )  ;
    // 保存校验和后,再次将报文转化为数据包
    Byte  [ ]  ByteSend = new Byte [ PacketSize  ]  ;
    index = packet.CountByte  (  ByteSend  )  ;
    //报文出错
    
    if  (   index != PacketSize  )
    {
     listBox1.Items.Add  (  "报文出现问题!"  )  ;
     return  ;
    }
    
    //发送不同TTL值的数据包
    for  (  int ittl=1 ; ittl <= 255 ; ittl++  )
    {
     Byte [ ]  ByteRecv = new Byte [ 256 ]  ;
     s.SetSocketOption  (  SocketOptionLevel.IP  , SocketOptionName.IpTimeToLive  , ittl  )  ;
     s.SetSocketOption  (  SocketOptionLevel.Socket  , SocketOptionName.SendTimeout  , 10000  )  ;
     s.SetSocketOption  (  SocketOptionLevel.Socket  , SocketOptionName.ReceiveTimeout  , 10000  )  ;
     //设定TTL和超时信息
     DateTime dt = DateTime.Now ;
     //获得当前时间
     int iRet = s.SendTo  (  ByteSend  , ByteSend.Length  , SocketFlags.None  , ipDEST  )  ;
     //发送ICMP报文
     if  (  iRet == -1  )
      listBox1.Items.Add  (  "发送数据出现错误!"  )  ;
     //接收返回数据
     iRet = s.ReceiveFrom  (  ByteRecv  , ByteRecv.Length  , SocketFlags.None  , ref epSRC  )  ;
     //计算发送数据到接收数据之间的时间差
     TimeSpan ts = DateTime.Now - dt ;
     //检测回应是否正确
     if  (  iRet == -1  )
      listBox1.Items.Add  (  "接收数据出现错误!"  )  ;
     listBox1.Items.Add  (  "TTL=" + ittl.ToString  (   )  + " IP=" +  (    (  IPEndPoint  )  epSRC  ) .Address.ToString  (   )  + " Time= " + ts.Milliseconds.ToString  (   )   )  ;
     //判断是否到达目的地址
     if   (  Dns.Resolve  (  textBox1.Text  ) .AddressList [ 0 ] .ToString  (   )  ==  (    (  IPEndPoint  )  epSRC  ) .Address.ToString  (   )   )
     {
      break ;
     }
     //超时错误
     if  (  ByteRecv [ 20 ]  != 11  )
     {
      listBox1.Items.Add  (  "出现超时误,请重试!"  )  ;
      break ;
     }
    }
   }
   catch  (  SocketException b  )
   {
    MessageBox.Show  (  b.Message  )  ;
   }
   catch  (  Exception ex  )
   {
    MessageBox.Show  (  ex.Message  )  ;
   }
  }
  public class IcmpPacket
  {
   private Byte _type ;     
   // 类型
   private Byte _subCode ;  
   // 代码
   private UInt16 _checkSum ;
   // 校验和
   private UInt16 _identifier ;  
   // 识别符
   private UInt16 _sequenceNumber ; 
   // 序列号
   private Byte  [ ]  _data ; 
   //选项数据
   public IcmpPacket  (  Byte type  , Byte subCode  , UInt16 checkSum  , UInt16 identifier  , UInt16 sequenceNumber  , int dataSize  )
   {
    _type = type ;
    _subCode = subCode ;
    _checkSum = checkSum ;
    _identifier = identifier ;
    _sequenceNumber = sequenceNumber ;
    _data=new Byte [ dataSize ]  ;
    //在数据中,写入指定的数据大小
    for   (  int i = 0 ; i < dataSize ; i++  )
    {
     //由于选项数据在此命令中并不重要,所以你可以改换任何你喜欢的字符 
     _data [ i ]  =   (  byte  ) '#' ;
    }
   }
   public UInt16 CheckSum
   {
    get
    {
     return _checkSum ;
    }
    set
    {
     _checkSum=value ;
    }
   }
   //初始化ICMP报文
   public int CountByte  (  Byte [ ]  buffer  )
   {

    Byte  [ ]  b_type = new Byte [ 1 ] { _type } ;
    Byte  [ ]  b_code = new Byte [ 1 ] { _subCode } ;
    Byte  [ ]  b_cksum = BitConverter.GetBytes  (  _checkSum  )  ;
    Byte  [ ]  b_id = BitConverter.GetBytes  (  _identifier  )  ;
    Byte  [ ]  b_seq = BitConverter.GetBytes  (  _sequenceNumber  )  ;
    int i = 0 ;
    Array.Copy  (   b_type  , 0  , buffer  , i  , b_type.Length   )  ;
    i+= b_type.Length ;
    Array.Copy  (   b_code  , 0  , buffer  , i  , b_code.Length   )  ;
    i+= b_code.Length ;
    Array.Copy  (   b_cksum  , 0  , buffer  ,i  , b_cksum.Length   )  ;
    i+= b_cksum.Length ;
    Array.Copy  (   b_id  , 0  , buffer  , i  , b_id.Length   )  ;
    i+= b_id.Length ;
    Array.Copy  (   b_seq  , 0  , buffer  , i  , b_seq.Length   )  ;
    i += b_seq.Length ;
    Array.Copy  (  _data  , 0  , buffer  , i  , _data.Length   )  ;
    i += _data.Length ;
    return i ;
   }
   //将整个ICMP报文信息和数据转化为Byte数据包 
   public static UInt16 SumOfCheck  (   UInt16 [ ]  buffer   )
   {
    int cksum = 0 ;
    for  (  int i = 0 ; i < buffer.Length ; i++  )
     cksum +=   (  int  )  buffer [ i ]  ;
    cksum =   (  cksum >> 16  )  +   (  cksum & 0xffff  )  ;
    cksum +=   (  cksum >> 16  )  ;
    return   (  UInt16  )   (  ~cksum  )  ;
   }
  }
 }
}

()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值