C#下实现ping功能

这段时间一直在学习C#, 以前一直搞网络的,还是从Ping程序的实现写起吧.
ping的调用方法如下:
    Ping mPing=new Ping();
    mPing.Pinging(“127.0.0.1“,255,65535);
    mPing.Receive(); //成功接收返回true,timeout 返回false
全部源代码如下:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace Ping
{
 /// <summary>
 /// Summary description for Ping.
 /// </summary>
 ///
 //
 //
 //IP Header
 public class IPHDR
 {
  public byte VIHL
  {
   get{return mVIHL;}
   set{mVIHL=value;}
  }private byte mVIHL;
  public byte TOS
  {
   get{return mTOS;}
   set{mTOS=value;}
  }private byte mTOS;
  public short TotLen
  {
   get{return mTotLen;}
   set{mTotLen=value;}
  }private short mTotLen;
  public short ID
  {
   get{return mID;}
   set{mID=value;}
  }private short mID;
  public short FlagOff
  {
   get{return mFlagOff;}
   set{mFlagOff=value;}
  }private short mFlagOff;
  public byte TTL
  {
   get{return mTTL;}
   set{mTTL=value;}
  }private byte mTTL;
  public byte Protocol
  {
   get{return mProtocol;}
   set{mProtocol=value;}
  }private byte mProtocol;
  public ushort Checksum
  {
   get{return mChecksum;}
   set{mChecksum = value;}
  }private ushort mChecksum;
  public ulong iaSrc
  {
   get{return miaSrc;}
   set{miaSrc=value;}
  }private ulong miaSrc;
  public ulong iaDst
  {
   get{return miaDst;}
   set{miaDst=value;}
  }private ulong miaDst;

  public static string Address(ulong obj)
  {
   byte s1=(byte)obj;
   byte s2=(byte)(obj>>8);
   byte s3=(byte)(obj>>16);
   byte s4=(byte)(obj>>24);
   return String.Format("{0}.{1}.{2}.{3}",s1,s2,s3,s4);//s1+"."+s2+"."+s3+"."+s4;
  }
  public void Encode(BinaryWriter writer)
  {
   writer.Write(VIHL);
   writer.Write(TOS);
   writer.Write((Int16)TotLen);
   writer.Write((Int16)ID);
   writer.Write((Int16)FlagOff);
   writer.Write(TTL);
   writer.Write(Protocol);
   writer.Write((UInt16)Checksum);
   writer.Write((UInt32)iaSrc);
   writer.Write((UInt32)iaDst);

  }
  public void Decode(BinaryReader reader)
  {
   VIHL=reader.ReadByte();
   TOS=reader.ReadByte();
   TotLen=reader.ReadInt16();
   ID=reader.ReadInt16();
   FlagOff=reader.ReadInt16();
   TTL=reader.ReadByte();
   Protocol=reader.ReadByte();
   Checksum=reader.ReadUInt16();
   iaSrc=reader.ReadUInt32();
   iaDst=reader.ReadUInt32();
  }

 }
 //ICMP Header;
 public class ICMPHDR
 {
  public byte Type
  {
   get{return mType;}
   set{mType=value;}
  }private byte mType;
  public byte Code
  {
   get{return mCode;}
   set{mCode=value;}
  }private byte mCode=0;
  public ushort Checksum
  {
   get{return mChecksum;}
   set{mChecksum=value;}
  }private ushort mChecksum=0;
  public ushort ID
  {
   get{return mID;}
   set{mID=value;}
  }private ushort mID;
  public ushort Seq
  {
   get{return mSeq;}
   set{mSeq=value;}
  }private ushort mSeq;
  public ulong tmSend
  {
   get{return mtmSend;}
   set{mtmSend=value;}
  }private ulong mtmSend;

  public int nTaskId
  {
   get{return mnTaskId;}
   set{mnTaskId=value;}
  }private int mnTaskId;
  public void Encode(BinaryWriter writer)
  {
   writer.Write(Type);
   writer.Write(Code);
   writer.Write((UInt16)Checksum);
   writer.Write((UInt16)ID);
   writer.Write((UInt16)Seq);
   writer.Write((UInt32)tmSend);
   writer.Write(nTaskId);
  }
  public void Decode(BinaryReader reader)
  {
   Type=reader.ReadByte();
   Code=reader.ReadByte();
   Checksum=reader.ReadUInt16();
   ID=reader.ReadUInt16();
   Seq=reader.ReadUInt16();
   tmSend=reader.ReadUInt32();
   nTaskId=reader.ReadInt32();
  }
  public uint Sum()
  {
   uint sum=0;
   sum +=(ushort)(Type+(Code<<8));
   sum +=(ushort)ID;
   sum +=(ushort)Seq;
   sum +=(ushort)tmSend;
   sum +=(ushort)(tmSend>>16);
   sum +=(ushort)nTaskId;
   sum +=(ushort)(nTaskId>>16);
   return sum;
  }
 }
 public class ECHOREQUEST
 {
  private char[] mChar;
  public ICMPHDR icmp=new ICMPHDR();
  public ECHOREQUEST(int size,char nChar)
  {
   mChar=new Char[size];
   for(int i=0;i<size;i++)
    mChar[i]=nChar;
  }
  public void Encode(BinaryWriter writer)
  {
   chksum();
   icmp.Encode(writer);
   writer.Write(mChar);
  }
/*  public void Decode(BinaryReader reader)
  {
   icmp.Decode(reader);
   string s=reader.ReadString();
   mChar=s.ToCharArray();
  }
*/  private void chksum()
  {
   uint sum=icmp.Sum();
   for(int i=0;i<mChar.Length;i+=2)
    sum +=(ushort)(mChar[i]+(mChar[i+1]<<8));
   //
   sum = (sum >> 16) + (sum & 0xffff); // add hi 16 to low 16
   sum += (sum >> 16);     // add carry
   short answer = (short)~sum;      // truncate to 16 bits
   icmp.Checksum=(ushort)answer;
  }
 }
 //ICMP Echo Reply
 public class ECHOREPLY
 {
  public IPHDR ipHdr=null;
  public ICMPHDR icmpHdr=null;
  public char[] cFiller;
  public void Decode(BinaryReader reader)
  {
   ipHdr=new IPHDR();
   ipHdr.Decode(reader);

   icmpHdr=new ICMPHDR();
   icmpHdr.Decode(reader);
   
   int bytes=(int)reader.BaseStream.Length;
//   cFiller=reader.ReadChars(8);
   cFiller=reader.ReadChars(bytes-36);
  }
 }
 public class StateObject
 {
  public Socket workSocket = null;              // Client socket.
  public const int BufferSize = 256;            // Size of receive buffer.
  public byte[] buffer = new byte[BufferSize];  // Receive buffer.
//  public StringBuilder sb = new StringBuilder();// Received data string.
 }

 public class Ping
 {
  Socket socket=null;
  int m_id;
  uint m_taskid;
  uint m_seq;
  System.Threading.ManualResetEvent recvDone=null;
  DateTime m_dtSend;
  public Ping()
  {
   m_seq=0;
   recvDone=new System.Threading.ManualResetEvent(false);
   socket=new Socket(AddressFamily.InterNetwork,SocketType.Raw,ProtocolType.Icmp);
   //
   // TODO: Add constructor logic here
   //
  }
  public bool Pinging(string addr,int id, uint taskid)
  {
   try
   {
    m_id=id;
    m_taskid=taskid;
    Byte[] byReq =FillEchoReq();

    //send to
    
    IPEndPoint lep = new IPEndPoint(IPAddress.Parse(addr), 0);


    socket.SendTo(byReq,lep);
   }
   catch(Exception e)
   {
    Console.WriteLine("Send error:"+e.ToString());
    return false;
   }
  
   return true;
  }
  private Byte[] FillEchoReq()
  {
   m_seq++;
   if(m_seq>1000)
    m_seq=1;
   ECHOREQUEST req=new ECHOREQUEST(8,'E');
   req.icmp.Type=8;
   req.icmp.Code=0;
   req.icmp.ID=(ushort)m_id;
   req.icmp.Seq=(ushort)m_seq;
   req.icmp.nTaskId=(int)m_taskid;
   m_dtSend=DateTime.Now;

   req.icmp.tmSend=(ulong)DateTime.Now.Ticks;
   MemoryStream stream=new MemoryStream();
   BinaryWriter writer=new BinaryWriter(stream);
   req.Encode(writer);

   int toReads=(int)stream.Length;
   //get Byte array.
   Byte[] byReq=stream.ToArray();

   stream.Close();
   return byReq;
  }

  private static uint iocntlCheck(Socket s)
  {
     
   // Set up the input and output byte arrays.
   byte[] inValue = BitConverter.GetBytes(0);
   byte[] outValue = BitConverter.GetBytes(0);

   // Check how many bytes have been received.
   s.IOControl(0x4004667F, inValue, outValue);
   uint bytesAvail = BitConverter.ToUInt32(outValue, 0);
   return bytesAvail;
  }
  //used to check reply data by sync
  public bool checkReply()
  {
   uint byAvail=iocntlCheck(socket);
   if(byAvail<=0)
    return false;
   try
   {
    Byte[] recv=new Byte[byAvail];
    socket.Receive(recv);
    return checkEchoReply(recv,(int)byAvail);
   }
   catch(Exception e)
   {
    Console.WriteLine(e.ToString());
    return false;
   }
  }
  //Directly analyze the byte array.

  public bool checkEchoReply1(Byte[] recv,int len)
  {
   if(len<36)
    return false;
   int ttl=recv[8];
   string src=recv[12]+"."+recv[13]+"."+recv[14]+"."+recv[15];
   string dst=recv[16]+"."+recv[17]+"."+recv[18]+"."+recv[19];
   int type=recv[20];
   if(type !=0)
    return false;
   //24,25, id
   int id=recv[24]+(recv[25]<<8);
   if(id !=m_id)
    return false;
   //26,27, seq
   int seq=recv[26]+(recv[27]<<8);
   //32,33,34,35, task id
   int taskid=recv[32]+(recv[33]<<8)+(recv[34]<<16)+(recv[35]<<24);
   if(taskid !=m_taskid)
    return false;
   int bytes= len-36;

   
   TimeSpan ts=DateTime.Now-m_dtSend;
   Console.WriteLine("Reply from {0}: bytes={1},icmp_seq={2},TTL={3},time={4} ms",
    src,bytes,seq,ttl ,ts.Milliseconds );

   return true;

  }
  //use IPHDR, ICMPHDR to analyze replyk data.
  public bool checkEchoReply(Byte[] recv,int len)
  {
   //20bytes ip pack.
   if(len<36)
    return false;
   MemoryStream stream=new MemoryStream(recv,0,len,false);
   BinaryReader reader=new BinaryReader(stream);
   ECHOREPLY reply=new ECHOREPLY();
   reply.Decode(reader);

   stream.Close();
   string dst,src;
   dst=IPHDR.Address(reply.ipHdr.iaDst);
   src=IPHDR.Address(reply.ipHdr.iaSrc);

   //type
   byte type=reply.icmpHdr.Type;
   //24,25 id
   int id=reply.icmpHdr.ID;
   //26,27,seq
   int seq=reply.icmpHdr.Seq ;
   //

   int bytes= len-36;

   //32,33,34,35, task id
   DateTime dt=new DateTime((long)reply.icmpHdr.tmSend);
//   Consdt.ToString();
   uint taskid=(uint)reply.icmpHdr.nTaskId;//(uint)(recv[32]+(recv[33]<<8)+(recv[34]<<16)+(recv[35]<<24));
   TimeSpan ts=DateTime.Now -m_dtSend;//dt;
   if(type == 0 && id == m_id && m_taskid==taskid)
   {
    Console.WriteLine("Reply from {0}: bytes={1},icmp_seq={2},TTL={3},time={4} ms",
     src,bytes,seq,reply.ipHdr.TTL ,ts.Milliseconds );

    return true;
   }
   else
   {
//    Console.WriteLine("Unknown data,{0},{1},type={2},icmp_seq={3}",
//     src,dst,type,seq);
   }
   return false;

  }
  public bool Receive()
  {
   try
   {
    recvDone.Reset();
    StateObject so=new StateObject();
    so.workSocket=socket;

//    socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReceiveTimeout,5000);

    IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
    EndPoint tempRemoteEP = (EndPoint)sender;

    socket.BeginReceiveFrom(so.buffer,0,StateObject.BufferSize,0,ref tempRemoteEP,new AsyncCallback(receiveCallBack),so);

    if(!recvDone.WaitOne())//.WaitOne(1000,false))
    {//receive timeout
     Console.WriteLine("Request timed out");
     return false;
    }

   }
   catch(Exception e)
   {
    Console.WriteLine("Fail,{0}",e.ToString());
    return false;
   }
   return true;
  }
  public void receiveCallBack(IAsyncResult ar)
  {
   try
   {
    StateObject obj=(StateObject)ar.AsyncState;
    Socket sock=obj.workSocket;
    IPEndPoint ep=new IPEndPoint(IPAddress.Any,0);
    EndPoint tempEP=(EndPoint)ep;
    int recvs=sock.EndReceiveFrom(ar,ref tempEP);
    if(checkEchoReply(obj.buffer,recvs))
     recvDone.Set();
    else
     sock.BeginReceiveFrom(obj.buffer,0,StateObject.BufferSize,0,ref tempEP,new AsyncCallback(receiveCallBack),obj);
//    Console.WriteLine("Address:{0}",((IPEndPoint)tempEP).Address);
   }
   catch(Exception e)
   {
    Console.WriteLine("CallBack Error:"+e.ToString());

   }
  }
  public void clear()
  {
   socket.Close();
  }
 }
}

呵呵,写的简单了点,大家可以先把code 复制下来,自己试试就一切ok...
欢迎来信交流, email/MSN:wugy006#163.net

        
  
 

  • 1
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

silverwgy

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值