C#下实现ping功能

王朝c#·作者佚名  2006-01-09
宽屏版  字体: |||超大  

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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
© 2005- 王朝网络 版权所有