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
{
/// <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();
}
}
}

时间: 2025-01-02 19:52:50

C#下实现ping功能的相关文章

纯Javascript实现ping功能的方法

 这篇文章主要介绍了纯Javascript实现ping功能的方法,实例分析了javascript实现ping功能的技巧,具有一定参考借鉴价值,需要的朋友可以参考下     本文实例讲述了纯Javascript实现ping功能的方法.分享给大家供大家参考.具体实现方法如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

ASP环境下邮件列表功能的实现 (一)

邮件列表(Mailing List)是当前最受欢迎的网络服务之一.本文通过一个示例系统的建设,介绍在ASP环境下邮件列表功能的实现方法. ChinaByte网络学院的<Java Mail API及其应用>一文介绍了在Java中简单邮件列表服务功能的实现方法,本文介绍的是类似功能在ASP应用中的实现.我们将通过一个示例系统具体说明其实现过程. 一.系统概貌 整个应用系统可以分为两个部分,即面向最终用户的功能和面向管理任务的功能.面向最终用户的功能主要包括:提供输入界面让用户输入个人信息(用户名字

ASP环境下邮件列表功能的实现 (一)(推荐)

邮件列表 邮件列表(Mailing List)是当前最受欢迎的网络服务之一.本文通过一个示例系统的建设,介绍在ASP环境下邮件列表功能的实现方法. ChinaByte网络学院的<Java Mail API及其应用>一文介绍了在Java中简单邮件列表服务功能的实现方法,本文介绍的是类似功能在ASP应用中的实现.我们将通过一个示例系统具体说明其实现过程. 一.系统概貌 整个应用系统可以分为两个部分,即面向最终用户的功能和面向管理任务的功能.面向最终用户的功能主要包括:提供输入界面让用户输入个人信息

Android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能

最近项目中需要用到ListView下拉刷新的功能,一开始想图省事,在网上直接找一个现成的,可是尝试了 网上多个版本的下拉刷新之后发现效果都不怎么理想.有些是因为功能不完整或有Bug,有些是因为使用起来 太复杂,十全十美的还真没找到.因此我也是放弃了在网上找现成代码的想法,自己花功夫编写了一种非常 简单的下拉刷新实现方案,现在拿出来和大家分享一下.相信在阅读完本篇文章之后,大家都可以在自己的 项目中一分钟引入下拉刷新功能. 首先讲一下实现原理.这里我们将采取的方案是使用组合View的方 式,先自定

Android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能

以下是我自己花功夫编写了一种非常简单的下拉刷新实现方案,现在拿出来和大家分享一下.相信在阅读完本篇文章之后,大家都可以在自己的项目中一分钟引入下拉刷新功能   最近项目中需要用到ListView下拉刷新的功能,一开始想图省事,在网上直接找一个现成的,可是尝试了网上多个版本的下拉刷新之后发现效果都不 怎么理想.有些是因为功能不完整或有Bug,有些是因为使用起来太复杂,十全十美的还真没找到.因此我也是放弃了在网上找现成代码的想法,自己花功夫编写 了一种非常简单的下拉刷新实现方案,现在拿出来和大家分享

纯javascript实现简单下拉刷新功能

 这篇文章主要介绍了纯javascript实现简单下拉刷新功能,没有借助任何的框架,十分简单实用,有需要的小伙伴来参考下吧.     代码很简单,实现的功能却很实用,直接奉上代码 CSS:   代码如下: <meta charset="utf-8" /> <title>Pull to Refresh</title> <meta name="viewport" content="width=device-width,

windows7系统下那些不为人知的功能

  那些隐藏在windows7系统下不为人知的小功能,相信很多人都不知道.尽管他们用了这个系统很久了.很熟练了,也不敢保证了如指掌.下面将为大家介绍怎样使用这些隐藏起来的功能,能够熟练地操作,有一些问题不用麻烦别人也能够自己解决了.windows7系统的用户这个系统下操作电脑更加的得心应手,希望大家看了之后,能得到有用的帮助. 截图工具 有许多简单的屏幕截图工具可以使用,不过你知道 Windows 中就有一个不错的吗?在 Windows 的搜索框中输入"snipping"就可以找到截图

win7系统下定时关机功能全面应用

win7系统下定时关机功能全面应用:怎么对win7系统设定关机等待时间 经常有用户会发现,在win7系统关机过程中,会出现一个等待系统关闭的提示,我们需要等一段时间才可以把电脑关闭,即使很多的用户已经习惯了这些默认设置,还是想要把关机时间缩短.那么该如何对关机等待时间进行设置呢?下面就来看看小编是怎么操作的. 1.首先,咱们同时按下win7键盘上的win+R快捷键打开电脑的运行窗口,之后,咱们在打开的运行窗口中输入regedit并单击回车,这样就可以打开电脑的注册表编辑器窗口了. 2.在打开的注

VC下做一个功能,双击列表控件,使得列表全屏显示,按Esc键恢复原来状态,怎么做?

问题描述 VC下做一个功能,双击列表控件,使得列表全屏显示,按Esc键恢复原来状态,怎么做? 使用List Control,双击它的时候能够变成全屏,按Esc键恢复原来状态 解决方案 是什么环境?如果是VB或者C#,你可以做一个窗口,不要边框和标题栏(controlbox FormBorderStyle),list control dock设置为fill响应keypress,如果是窗口,就切换到全屏的那个窗口,否则切换回来. 解决方案二: 处理db_click双击消息,然后MoveWindow调