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