这段时间一直在学习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]<<8));" chksum()="" chksum();="" decode(binaryreader="" encode(binarywriter="" for(int="" i="0;i<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);="" {="" }="">> 16) + (sum & 0xffff); // add hi 16 to low 16
2sum += (sum >> 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>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<=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<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]<<8);
144if(id !=m_id)
145return false;
146//26,27, seq
147int seq=recv[26]+(recv[27]<<8);
148//32,33,34,35, task id
149int taskid=recv[32]+(recv[33]<<8)+(recv[34]<<16)+(recv[35]<<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<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]<<8)+(recv[34]<<16)+(recv[35]<<24));
192TimeSpan ts=DateTime.Now -m_dtSend;//dt;
193if(type == 0 && id == m_id && 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++)>