这段时间一直在学习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();
 }
 }
}