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
{
///

1<summary>   
2/// Summary description for Ping.   
3/// </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

  1<size;i++) *="" +="(ushort)(mChar[i]+(mChar[i+1]&lt;&lt;8));" chksum()="" chksum();="" decode(binaryreader="" encode(binarywriter="" for(int="" i="0;i&lt;mChar.Length;i+=2)" icmp.decode(reader);="" icmp.encode(writer);="" mchar="s.ToCharArray();" mchar[i]="nChar;" private="" public="" reader)="" s="reader.ReadString();" string="" sum="(sum" uint="" void="" writer)="" writer.write(mchar);="" {="" }="">&gt; 16) + (sum &amp; 0xffff); // add hi 16 to low 16   
  2sum += (sum &gt;&gt; 16); // add carry   
  3short answer = (short)~sum; // truncate to 16 bits   
  4icmp.Checksum=(ushort)answer;   
  5}   
  6}   
  7//ICMP Echo Reply   
  8public class ECHOREPLY   
  9{   
 10public IPHDR ipHdr=null;   
 11public ICMPHDR icmpHdr=null;   
 12public char[] cFiller;   
 13public void Decode(BinaryReader reader)   
 14{   
 15ipHdr=new IPHDR();   
 16ipHdr.Decode(reader); 
 17
 18icmpHdr=new ICMPHDR();   
 19icmpHdr.Decode(reader);   
 20  
 21int bytes=(int)reader.BaseStream.Length;   
 22// cFiller=reader.ReadChars(8);   
 23cFiller=reader.ReadChars(bytes-36);   
 24}   
 25}   
 26public class StateObject   
 27{   
 28public Socket workSocket = null; // Client socket.   
 29public const int BufferSize = 256; // Size of receive buffer.   
 30public byte[] buffer = new byte[BufferSize]; // Receive buffer.   
 31// public StringBuilder sb = new StringBuilder();// Received data string.   
 32} 
 33
 34public class Ping   
 35{   
 36Socket socket=null;   
 37int m_id;   
 38uint m_taskid;   
 39uint m_seq;   
 40System.Threading.ManualResetEvent recvDone=null;   
 41DateTime m_dtSend;   
 42public Ping()   
 43{   
 44m_seq=0;   
 45recvDone=new System.Threading.ManualResetEvent(false);   
 46socket=new Socket(AddressFamily.InterNetwork,SocketType.Raw,ProtocolType.Icmp);   
 47//   
 48// TODO: Add constructor logic here   
 49//   
 50}   
 51public bool Pinging(string addr,int id, uint taskid)   
 52{   
 53try   
 54{   
 55m_id=id;   
 56m_taskid=taskid;   
 57Byte[] byReq =FillEchoReq(); 
 58
 59//send to   
 60  
 61IPEndPoint lep = new IPEndPoint(IPAddress.Parse(addr), 0); 
 62
 63  
 64socket.SendTo(byReq,lep);   
 65}   
 66catch(Exception e)   
 67{   
 68Console.WriteLine("Send error:"+e.ToString());   
 69return false;   
 70}   
 71  
 72return true;   
 73}   
 74private Byte[] FillEchoReq()   
 75{   
 76m_seq++;   
 77if(m_seq&gt;1000)   
 78m_seq=1;   
 79ECHOREQUEST req=new ECHOREQUEST(8,'E');   
 80req.icmp.Type=8;   
 81req.icmp.Code=0;   
 82req.icmp.ID=(ushort)m_id;   
 83req.icmp.Seq=(ushort)m_seq;   
 84req.icmp.nTaskId=(int)m_taskid;   
 85m_dtSend=DateTime.Now; 
 86
 87req.icmp.tmSend=(ulong)DateTime.Now.Ticks;   
 88MemoryStream stream=new MemoryStream();   
 89BinaryWriter writer=new BinaryWriter(stream);   
 90req.Encode(writer); 
 91
 92int toReads=(int)stream.Length;   
 93//get Byte array.   
 94Byte[] byReq=stream.ToArray(); 
 95
 96stream.Close();   
 97return byReq;   
 98} 
 99
100private static uint iocntlCheck(Socket s)   
101{   
102  
103// Set up the input and output byte arrays.   
104byte[] inValue = BitConverter.GetBytes(0);   
105byte[] outValue = BitConverter.GetBytes(0); 
106
107// Check how many bytes have been received.   
108s.IOControl(0x4004667F, inValue, outValue);   
109uint bytesAvail = BitConverter.ToUInt32(outValue, 0);   
110return bytesAvail;   
111}   
112//used to check reply data by sync   
113public bool checkReply()   
114{   
115uint byAvail=iocntlCheck(socket);   
116if(byAvail&lt;=0)   
117return false;   
118try   
119{   
120Byte[] recv=new Byte[byAvail];   
121socket.Receive(recv);   
122return checkEchoReply(recv,(int)byAvail);   
123}   
124catch(Exception e)   
125{   
126Console.WriteLine(e.ToString());   
127return false;   
128}   
129}   
130//Directly analyze the byte array. 
131
132public bool checkEchoReply1(Byte[] recv,int len)   
133{   
134if(len&lt;36)   
135return false;   
136int ttl=recv[8];   
137string src=recv[12]+"."+recv[13]+"."+recv[14]+"."+recv[15];   
138string dst=recv[16]+"."+recv[17]+"."+recv[18]+"."+recv[19];   
139int type=recv[20];   
140if(type !=0)   
141return false;   
142//24,25, id   
143int id=recv[24]+(recv[25]&lt;&lt;8);   
144if(id !=m_id)   
145return false;   
146//26,27, seq   
147int seq=recv[26]+(recv[27]&lt;&lt;8);   
148//32,33,34,35, task id   
149int taskid=recv[32]+(recv[33]&lt;&lt;8)+(recv[34]&lt;&lt;16)+(recv[35]&lt;&lt;24);   
150if(taskid !=m_taskid)   
151return false;   
152int bytes= len-36; 
153
154  
155TimeSpan ts=DateTime.Now-m_dtSend;   
156Console.WriteLine("Reply from {0}: bytes={1},icmp_seq={2},TTL={3},time={4} ms",   
157src,bytes,seq,ttl ,ts.Milliseconds ); 
158
159return true; 
160
161}   
162//use IPHDR, ICMPHDR to analyze replyk data.   
163public bool checkEchoReply(Byte[] recv,int len)   
164{   
165//20bytes ip pack.   
166if(len&lt;36)   
167return false;   
168MemoryStream stream=new MemoryStream(recv,0,len,false);   
169BinaryReader reader=new BinaryReader(stream);   
170ECHOREPLY reply=new ECHOREPLY();   
171reply.Decode(reader); 
172
173stream.Close();   
174string dst,src;   
175dst=IPHDR.Address(reply.ipHdr.iaDst);   
176src=IPHDR.Address(reply.ipHdr.iaSrc); 
177
178//type   
179byte type=reply.icmpHdr.Type;   
180//24,25 id   
181int id=reply.icmpHdr.ID;   
182//26,27,seq   
183int seq=reply.icmpHdr.Seq ;   
184// 
185
186int bytes= len-36; 
187
188//32,33,34,35, task id   
189DateTime dt=new DateTime((long)reply.icmpHdr.tmSend);   
190// Consdt.ToString();   
191uint taskid=(uint)reply.icmpHdr.nTaskId;//(uint)(recv[32]+(recv[33]&lt;&lt;8)+(recv[34]&lt;&lt;16)+(recv[35]&lt;&lt;24));   
192TimeSpan ts=DateTime.Now -m_dtSend;//dt;   
193if(type == 0 &amp;&amp; id == m_id &amp;&amp; m_taskid==taskid)   
194{   
195Console.WriteLine("Reply from {0}: bytes={1},icmp_seq={2},TTL={3},time={4} ms",   
196src,bytes,seq,reply.ipHdr.TTL ,ts.Milliseconds ); 
197
198return true;   
199}   
200else   
201{   
202// Console.WriteLine("Unknown data,{0},{1},type={2},icmp_seq={3}",   
203// src,dst,type,seq);   
204}   
205return false; 
206
207}   
208public bool Receive()   
209{   
210try   
211{   
212recvDone.Reset();   
213StateObject so=new StateObject();   
214so.workSocket=socket; 
215
216// socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReceiveTimeout,5000); 
217
218IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);   
219EndPoint tempRemoteEP = (EndPoint)sender; 
220
221socket.BeginReceiveFrom(so.buffer,0,StateObject.BufferSize,0,ref tempRemoteEP,new AsyncCallback(receiveCallBack),so); 
222
223if(!recvDone.WaitOne())//.WaitOne(1000,false))   
224{//receive timeout   
225Console.WriteLine("Request timed out");   
226return false;   
227} 
228
229}   
230catch(Exception e)   
231{   
232Console.WriteLine("Fail,{0}",e.ToString());   
233return false;   
234}   
235return true;   
236}   
237public void receiveCallBack(IAsyncResult ar)   
238{   
239try   
240{   
241StateObject obj=(StateObject)ar.AsyncState;   
242Socket sock=obj.workSocket;   
243IPEndPoint ep=new IPEndPoint(IPAddress.Any,0);   
244EndPoint tempEP=(EndPoint)ep;   
245int recvs=sock.EndReceiveFrom(ar,ref tempEP);   
246if(checkEchoReply(obj.buffer,recvs))   
247recvDone.Set();   
248else   
249sock.BeginReceiveFrom(obj.buffer,0,StateObject.BufferSize,0,ref tempEP,new AsyncCallback(receiveCallBack),obj);   
250// Console.WriteLine("Address:{0}",((IPEndPoint)tempEP).Address);   
251}   
252catch(Exception e)   
253{   
254Console.WriteLine("CallBack Error:"+e.ToString()); 
255
256}   
257}   
258public void clear()   
259{   
260socket.Close();   
261}   
262}   
263}   
264  
265呵呵,写的简单了点,大家可以先把code 复制下来,自己试试就一切ok...   
266欢迎来信交流, email/MSN:wugy006#163.net</size;i++)>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus