为了了解Icmp协议,自己写了一个
using System;
using System.Text;
using Pierce.AttributeClass;
namespace Pierce.Icmp
{
/// <summary>
/// Icmp:Icmp Protocol
/// </summary>
[LastModified("2005-10-11","Icmp Protocol")]
public class Icmp
{
private eType type; //1 Byte Type
private eCode code; //1 Byte Code
private UInt16 Checksum; //2 Bytes CheckSum
private int Messagesize; //Message Size,Include Identify,Seq,Content
private int Packetsize; //Icmp package Size
public byte[] Message = new byte[1024]; //接收回复的byte[]
private byte[] Data=null; //存储Icmp包信息
private static UInt16 sequence=0; //顺序号
private static UInt16 identify=0; //认证号
private string content; //发送信息
private byte[] byContent; //发送信息的数组
/// <summary>
/// Icmp Type 枚举
/// </summary>
public enum eType:byte
{
EchoReply=0,
DestinationUnreachable=3,
SourceQuench=4,
Redirect=5,
EchoRequest=8,
TimeExceeded=11,
ParameterProblem=12,
TimeStampRequest=13,
TimeStampReply=14,
InformationRequest=15,
InformationReply=16
}
/// <summary>
/// Icmp Code 枚举
/// </summary>
public enum eCode:byte
{
NetworkUnreachable=0,
HostUnreachable=1,
ProtocolUnreachable=2,
PortUnreachable=3,
FragmentationNeededAndDFFlagSet=4,
SourceRouteFailed=5,
DestinationNetworkUnknow=6,
DestionationHostUnknow=7,
SourceHostIsolated=8,
CommunicationWithDestinationNetworkProhibited=9,
CommunicationWithDestinationHostProhibited=10,
NetworkUnreachableForTypeOfService=11,
HostUnreachableForTypeOfService=12
}
/// <summary>
/// 属性,读写,获取,设置Type
/// </summary>
internal eType Type
{
get{return type;}
set{type=value;}
}
/// <summary>
/// 属性,读写,获取、设置Code
/// </summary>
internal eCode Code
{
get{return code;}
set{code=value;}
}
/// <summary>
/// 属性,只读,返回认证号
/// </summary>
internal static UInt16 Identify
{
get{return identify;}
}
/// <summary>
/// 属性,制度,返回序列号
/// </summary>
internal static UInt16 Sequence
{
get{return sequence;}
}
/// <summary>
/// 属性,读写,设置,返回发送内容
/// </summary>
internal string Content
{
get{return content;}
set
{
//获取发送信息内容,并转换为字节数组
content=value;
byContent=Encoding.ASCII.GetBytes(content);
//获取发送信息长度,包括Identify+Sequence+Content
Messagesize=byContent.Length+4;
//因为MessageSize不包括type,code,checksum,所以要+4
Packetsize=Messagesize+4;
//保证是2的整数倍
if(IfDivision2(Packetsize)==false)
{
Data = new byte[Packetsize +1];
}
else
{
Data=new byte[Packetsize];
}
}
}
/// <summary>
/// 生成认证号
/// </summary>
/// <returns>返回认证号</returns>
private UInt16 getIdentify()
{
try
{
identify++;
}
catch
{
identify=0;
}
return identify;
}
/// <summary>
/// 生成顺序号
/// </summary>
/// <returns>返回顺序号</returns>
private UInt16 getSequence()
{
try
{
sequence++;
}
catch
{
sequence=0;
}
return sequence;
}
/// <summary>
/// 获取整个Icmp包的字节数组
/// </summary>
/// <returns></returns>
internal byte[] IcmpByteArray()
{
//设置checksum的初始值为0,计算实际的Checksum
UInt16 identi=0;
UInt16 seq=0;
this.Checksum=0;
this.Checksum=this.getChecksum(out identi,out seq);
//获取Icmp包的数组
byte[] byteIcmp=this.getBytes(identi,seq);
//返回Icmp包的数组
return byteIcmp;
}
/// <summary>
/// 属性,只读,获取MessageSize, 包括Identi+Seq+Content,
/// 读取收到的Icmp包时使用
/// </summary>
internal int MessageSize
{
get
{
return Messagesize;
}
}
/// <summary>
/// default Constructor
/// </summary>
internal Icmp()
{
}
/// <summary>
/// Constructor Override,Receive Response and Parse It
/// Because Received Packet include Ip Packet,so we should get our content from position 20
/// </summary>
/// <param name="data">接收到的IP Package,包含了IP Header共20bytes长度</param>
/// <param name="size">总长度</param>
internal Icmp(byte[] data, int size)
{
type = (eType)Enum.Parse(typeof(eType),data[20].ToString());
code = (eCode)Enum.Parse(typeof(eCode),data[21].ToString());
Checksum = BitConverter.ToUInt16(data, 22); //校验和
Messagesize = size - 24; //Message的长度
Message=new byte[Messagesize]; //设置Message长度
Buffer.BlockCopy(data, 24, Message, 0, Messagesize);
}
/// <summary>
/// 检查所给的参数是否可以被2整除,是:True,否:False
/// </summary>
/// <param name="Number">给定参数</param>
/// <returns>如果是,返回True,不是,返回False</returns>
[LastModified("2005-10-12","计算给定参数是否是2的整数倍")]
private bool IfDivision2(int Number)
{
int yu=Number%2;
if(yu==0)
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// 把Icmp包转换为byte[],除了checksum的值是0外,其他的都是实际值,
/// </summary>
/// <param name="identi">认证号</param>
/// <param name="seq">序列号</param>
/// <returns>返回Icmp的字节数组</returns>
[LastModified("2005-10-12","将Checksum=0时,把Icmp包转换为Byte[],发送请求时用")]
private byte[] getBytes(UInt16 identi,UInt16 seq)
{
//设置初始值,如果内容为空,那么设置为空,
//type=0,那么位8,即Echo Request
//code=0
if(content==null)
{
content="";
}
if(type==0)
{
type=eType.EchoRequest;
}
if(code==0)
{
code=eCode.NetworkUnreachable;
}
//位移变量
int cursor=0;
//加入Type
Buffer.BlockCopy(BitConverter.GetBytes((byte)type), 0, Data, cursor, 1);
cursor++;
//加入Code
Buffer.BlockCopy(BitConverter.GetBytes((byte)code), 0, Data, cursor, 1);
cursor++;
//加入CheckSum
Buffer.BlockCopy(BitConverter.GetBytes(Checksum), 0, Data, cursor, 2);
cursor+=2;
//加入Message Content的Identify,2 Bytes
Buffer.BlockCopy(BitConverter.GetBytes(identi),0, Data, cursor,2);
cursor+=2;
//加入MessageContent的Sequence,2 Bytes
Buffer.BlockCopy(BitConverter.GetBytes(seq),0,Data,cursor,2);
cursor+=2;
//加入content
Buffer.BlockCopy
(
byContent,0,Data,cursor,byContent.Length
);
//
return Data;
}
/// <summary>
/// 生成Icmp包的byte[],同时传出认证号和序列号
/// </summary>
/// <param name="identi">认证号</param>
/// <param name="seq">序列号</param>
/// <returns>返回的Byte[]</returns>
[LastModified("2005-10-12","把Icmp包装换位Byte[]")]
internal byte[] getBytes(out UInt16 identi,out UInt16 seq)
{
//设置初始值
if(content==null)
{
content="";
}
if(type==0)
{
type=eType.EchoRequest;
}
if(code==0)
{
code=eCode.NetworkUnreachable;
}
//位移变量
int cursor=0;
//加入Type
Buffer.BlockCopy(BitConverter.GetBytes((byte)type), 0, Data, cursor, 1);
cursor++;
//加入Code
Buffer.BlockCopy(BitConverter.GetBytes((byte)code), 0, Data, cursor, 1);
cursor++;
//加入CheckSum
Buffer.BlockCopy(BitConverter.GetBytes(Checksum), 0, Data, cursor, 2);
cursor+=2;
//加入Message Content的Identify,2 Bytes
identi=getIdentify();
Buffer.BlockCopy(BitConverter.GetBytes(identi),0, Data, cursor,2);
cursor+=2;
//加入MessageContent的Sequence,2 Bytes
seq=getSequence();
Buffer.BlockCopy(BitConverter.GetBytes(seq),0,Data,cursor,2);
cursor+=2;
//加入content
Buffer.BlockCopy
(
byContent,0,Data,cursor,byContent.Length
);
//
return Data;
}
/// <summary>
/// Method to Calcu CheckSum
/// 每16位循环相加,进位加在末尾,和再求反
/// </summary>
/// <param name="identi">传出值的参数,做认证用</param>
/// <param name="seq" >传出值的参数,标记序列号</param>
/// <returns>return UInt16 value</returns>
[LastModified("2005-10-12","计算Checksum")]
private UInt16 getChecksum(out UInt16 identi,out UInt16 seq)
{
UInt32 chcksm = 0;
byte[] data = getBytes(out identi,out seq);
int index = 0;
//每16位循环相加
while ( index < Packetsize)
{
//把data中的每2个byte,转换为UInt16,然后加到chcksm中
chcksm += Convert.ToUInt32(BitConverter.ToUInt16(data, index));
index += 2;
}
//chcksm右移16位,然后同chcksm同0xffff相与的值相加
//和值的小16位同大16位相加,即进位加在末尾
chcksm = (chcksm >> 16) + (chcksm & 0xffff);
//chchsm在加chcksm右移16位的值
//同样是保证进位加在末尾
chcksm += (chcksm >> 16);
//chchsm取反,转换为UInt16
return (UInt16)(~chcksm);
}
/// <summary>
/// 计算整个Icmp包的Uint16值,如果为0,说明包没有出现传输错误,
/// 因为Checksum的值为其他字段的值的和再求反,所以如果在加上Checksum,
/// 那么得到全1的byte,再求反,结果为0
/// </summary>
/// <param name="data">接收到的数组</param>
/// <param name="packetsize">数组长度</param>
/// <returns></returns>
[LastModified("205-10-13","检验收到的数组传输中是否发生错误")]
internal UInt16 CalcuIcmpPack(byte[] data,int packetsize)
{
UInt32 chcksm = 0;
int index = 0;
//每16位循环相加
while ( index < packetsize)
{
//把data中的每2个byte,转换为UInt16,然后加到chcksm中
chcksm += Convert.ToUInt32(BitConverter.ToUInt16(data, index));
index += 2;
}
//chcksm右移16位,然后同chcksm同0xffff相与的值相加
//和值的小16位同大16位相加,即进位加在末尾
chcksm = (chcksm >> 16) + (chcksm & 0xffff);
//chchsm在加chcksm右移16位的值
//同样是保证进位加在末尾
chcksm += (chcksm >> 16);
//chchsm取反,转换为UInt16
return (UInt16)(~chcksm);
}
}
}
以上是协议的实现,下面是协议的使用using System.Text;
using Pierce.AttributeClass;
namespace Pierce.Icmp
{
/// <summary>
/// Icmp:Icmp Protocol
/// </summary>
[LastModified("2005-10-11","Icmp Protocol")]
public class Icmp
{
private eType type; //1 Byte Type
private eCode code; //1 Byte Code
private UInt16 Checksum; //2 Bytes CheckSum
private int Messagesize; //Message Size,Include Identify,Seq,Content
private int Packetsize; //Icmp package Size
public byte[] Message = new byte[1024]; //接收回复的byte[]
private byte[] Data=null; //存储Icmp包信息
private static UInt16 sequence=0; //顺序号
private static UInt16 identify=0; //认证号
private string content; //发送信息
private byte[] byContent; //发送信息的数组
/// <summary>
/// Icmp Type 枚举
/// </summary>
public enum eType:byte
{
EchoReply=0,
DestinationUnreachable=3,
SourceQuench=4,
Redirect=5,
EchoRequest=8,
TimeExceeded=11,
ParameterProblem=12,
TimeStampRequest=13,
TimeStampReply=14,
InformationRequest=15,
InformationReply=16
}
/// <summary>
/// Icmp Code 枚举
/// </summary>
public enum eCode:byte
{
NetworkUnreachable=0,
HostUnreachable=1,
ProtocolUnreachable=2,
PortUnreachable=3,
FragmentationNeededAndDFFlagSet=4,
SourceRouteFailed=5,
DestinationNetworkUnknow=6,
DestionationHostUnknow=7,
SourceHostIsolated=8,
CommunicationWithDestinationNetworkProhibited=9,
CommunicationWithDestinationHostProhibited=10,
NetworkUnreachableForTypeOfService=11,
HostUnreachableForTypeOfService=12
}
/// <summary>
/// 属性,读写,获取,设置Type
/// </summary>
internal eType Type
{
get{return type;}
set{type=value;}
}
/// <summary>
/// 属性,读写,获取、设置Code
/// </summary>
internal eCode Code
{
get{return code;}
set{code=value;}
}
/// <summary>
/// 属性,只读,返回认证号
/// </summary>
internal static UInt16 Identify
{
get{return identify;}
}
/// <summary>
/// 属性,制度,返回序列号
/// </summary>
internal static UInt16 Sequence
{
get{return sequence;}
}
/// <summary>
/// 属性,读写,设置,返回发送内容
/// </summary>
internal string Content
{
get{return content;}
set
{
//获取发送信息内容,并转换为字节数组
content=value;
byContent=Encoding.ASCII.GetBytes(content);
//获取发送信息长度,包括Identify+Sequence+Content
Messagesize=byContent.Length+4;
//因为MessageSize不包括type,code,checksum,所以要+4
Packetsize=Messagesize+4;
//保证是2的整数倍
if(IfDivision2(Packetsize)==false)
{
Data = new byte[Packetsize +1];
}
else
{
Data=new byte[Packetsize];
}
}
}
/// <summary>
/// 生成认证号
/// </summary>
/// <returns>返回认证号</returns>
private UInt16 getIdentify()
{
try
{
identify++;
}
catch
{
identify=0;
}
return identify;
}
/// <summary>
/// 生成顺序号
/// </summary>
/// <returns>返回顺序号</returns>
private UInt16 getSequence()
{
try
{
sequence++;
}
catch
{
sequence=0;
}
return sequence;
}
/// <summary>
/// 获取整个Icmp包的字节数组
/// </summary>
/// <returns></returns>
internal byte[] IcmpByteArray()
{
//设置checksum的初始值为0,计算实际的Checksum
UInt16 identi=0;
UInt16 seq=0;
this.Checksum=0;
this.Checksum=this.getChecksum(out identi,out seq);
//获取Icmp包的数组
byte[] byteIcmp=this.getBytes(identi,seq);
//返回Icmp包的数组
return byteIcmp;
}
/// <summary>
/// 属性,只读,获取MessageSize, 包括Identi+Seq+Content,
/// 读取收到的Icmp包时使用
/// </summary>
internal int MessageSize
{
get
{
return Messagesize;
}
}
/// <summary>
/// default Constructor
/// </summary>
internal Icmp()
{
}
/// <summary>
/// Constructor Override,Receive Response and Parse It
/// Because Received Packet include Ip Packet,so we should get our content from position 20
/// </summary>
/// <param name="data">接收到的IP Package,包含了IP Header共20bytes长度</param>
/// <param name="size">总长度</param>
internal Icmp(byte[] data, int size)
{
type = (eType)Enum.Parse(typeof(eType),data[20].ToString());
code = (eCode)Enum.Parse(typeof(eCode),data[21].ToString());
Checksum = BitConverter.ToUInt16(data, 22); //校验和
Messagesize = size - 24; //Message的长度
Message=new byte[Messagesize]; //设置Message长度
Buffer.BlockCopy(data, 24, Message, 0, Messagesize);
}
/// <summary>
/// 检查所给的参数是否可以被2整除,是:True,否:False
/// </summary>
/// <param name="Number">给定参数</param>
/// <returns>如果是,返回True,不是,返回False</returns>
[LastModified("2005-10-12","计算给定参数是否是2的整数倍")]
private bool IfDivision2(int Number)
{
int yu=Number%2;
if(yu==0)
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// 把Icmp包转换为byte[],除了checksum的值是0外,其他的都是实际值,
/// </summary>
/// <param name="identi">认证号</param>
/// <param name="seq">序列号</param>
/// <returns>返回Icmp的字节数组</returns>
[LastModified("2005-10-12","将Checksum=0时,把Icmp包转换为Byte[],发送请求时用")]
private byte[] getBytes(UInt16 identi,UInt16 seq)
{
//设置初始值,如果内容为空,那么设置为空,
//type=0,那么位8,即Echo Request
//code=0
if(content==null)
{
content="";
}
if(type==0)
{
type=eType.EchoRequest;
}
if(code==0)
{
code=eCode.NetworkUnreachable;
}
//位移变量
int cursor=0;
//加入Type
Buffer.BlockCopy(BitConverter.GetBytes((byte)type), 0, Data, cursor, 1);
cursor++;
//加入Code
Buffer.BlockCopy(BitConverter.GetBytes((byte)code), 0, Data, cursor, 1);
cursor++;
//加入CheckSum
Buffer.BlockCopy(BitConverter.GetBytes(Checksum), 0, Data, cursor, 2);
cursor+=2;
//加入Message Content的Identify,2 Bytes
Buffer.BlockCopy(BitConverter.GetBytes(identi),0, Data, cursor,2);
cursor+=2;
//加入MessageContent的Sequence,2 Bytes
Buffer.BlockCopy(BitConverter.GetBytes(seq),0,Data,cursor,2);
cursor+=2;
//加入content
Buffer.BlockCopy
(
byContent,0,Data,cursor,byContent.Length
);
//
return Data;
}
/// <summary>
/// 生成Icmp包的byte[],同时传出认证号和序列号
/// </summary>
/// <param name="identi">认证号</param>
/// <param name="seq">序列号</param>
/// <returns>返回的Byte[]</returns>
[LastModified("2005-10-12","把Icmp包装换位Byte[]")]
internal byte[] getBytes(out UInt16 identi,out UInt16 seq)
{
//设置初始值
if(content==null)
{
content="";
}
if(type==0)
{
type=eType.EchoRequest;
}
if(code==0)
{
code=eCode.NetworkUnreachable;
}
//位移变量
int cursor=0;
//加入Type
Buffer.BlockCopy(BitConverter.GetBytes((byte)type), 0, Data, cursor, 1);
cursor++;
//加入Code
Buffer.BlockCopy(BitConverter.GetBytes((byte)code), 0, Data, cursor, 1);
cursor++;
//加入CheckSum
Buffer.BlockCopy(BitConverter.GetBytes(Checksum), 0, Data, cursor, 2);
cursor+=2;
//加入Message Content的Identify,2 Bytes
identi=getIdentify();
Buffer.BlockCopy(BitConverter.GetBytes(identi),0, Data, cursor,2);
cursor+=2;
//加入MessageContent的Sequence,2 Bytes
seq=getSequence();
Buffer.BlockCopy(BitConverter.GetBytes(seq),0,Data,cursor,2);
cursor+=2;
//加入content
Buffer.BlockCopy
(
byContent,0,Data,cursor,byContent.Length
);
//
return Data;
}
/// <summary>
/// Method to Calcu CheckSum
/// 每16位循环相加,进位加在末尾,和再求反
/// </summary>
/// <param name="identi">传出值的参数,做认证用</param>
/// <param name="seq" >传出值的参数,标记序列号</param>
/// <returns>return UInt16 value</returns>
[LastModified("2005-10-12","计算Checksum")]
private UInt16 getChecksum(out UInt16 identi,out UInt16 seq)
{
UInt32 chcksm = 0;
byte[] data = getBytes(out identi,out seq);
int index = 0;
//每16位循环相加
while ( index < Packetsize)
{
//把data中的每2个byte,转换为UInt16,然后加到chcksm中
chcksm += Convert.ToUInt32(BitConverter.ToUInt16(data, index));
index += 2;
}
//chcksm右移16位,然后同chcksm同0xffff相与的值相加
//和值的小16位同大16位相加,即进位加在末尾
chcksm = (chcksm >> 16) + (chcksm & 0xffff);
//chchsm在加chcksm右移16位的值
//同样是保证进位加在末尾
chcksm += (chcksm >> 16);
//chchsm取反,转换为UInt16
return (UInt16)(~chcksm);
}
/// <summary>
/// 计算整个Icmp包的Uint16值,如果为0,说明包没有出现传输错误,
/// 因为Checksum的值为其他字段的值的和再求反,所以如果在加上Checksum,
/// 那么得到全1的byte,再求反,结果为0
/// </summary>
/// <param name="data">接收到的数组</param>
/// <param name="packetsize">数组长度</param>
/// <returns></returns>
[LastModified("205-10-13","检验收到的数组传输中是否发生错误")]
internal UInt16 CalcuIcmpPack(byte[] data,int packetsize)
{
UInt32 chcksm = 0;
int index = 0;
//每16位循环相加
while ( index < packetsize)
{
//把data中的每2个byte,转换为UInt16,然后加到chcksm中
chcksm += Convert.ToUInt32(BitConverter.ToUInt16(data, index));
index += 2;
}
//chcksm右移16位,然后同chcksm同0xffff相与的值相加
//和值的小16位同大16位相加,即进位加在末尾
chcksm = (chcksm >> 16) + (chcksm & 0xffff);
//chchsm在加chcksm右移16位的值
//同样是保证进位加在末尾
chcksm += (chcksm >> 16);
//chchsm取反,转换为UInt16
return (UInt16)(~chcksm);
}
}
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Pierce.AttributeClass;
namespace Pierce.Icmp
{
/// <summary>
/// UseIcmp :使用Icmp协议
/// </summary>
[LastModified("2005-10-13","使用Icmp协议")]
public class UseIcmp
{
private Socket host; //Socket连接
private int receiveTime; //接收时间上限
private int sendTime; //发送时间上限
/// <summary>
/// 属性,读写,接收时间上限
/// </summary>
public int ReceiveTime
{
get{return receiveTime;}
set
{
receiveTime=value;
host.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout, receiveTime);
}
}
/// <summary>
/// 属性,读写,发送时间上限
/// </summary>
public int SendTime
{
get
{
return sendTime;
}
set
{
sendTime=value;
host.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.SendTimeout, sendTime);
}
}
/// <summary>
/// 构造函数,初始化Socket
/// </summary>
public UseIcmp()
{
host = new Socket(AddressFamily.InterNetwork, SocketType.Raw,
ProtocolType.Icmp);
}
/// <summary>
/// 给指定地址,发送指定内容的Icmp包,并接受恢复
/// 如果收到恢复,那么返回True,否则,返回False
/// </summary>
/// <param name="Ip">指定Ip地址</param>
/// <param name="Content">指定发送信息</param>
/// <returns>返回值</returns>
public bool SendIcmp(string Ip,string Content)
{
bool ifOk=false; //是否成功
int recv; //接收到的字节数
//目的信息
IPEndPoint iep = new IPEndPoint(IPAddress.Parse(Ip), 0);
EndPoint ep = (EndPoint)iep;
//设置Type,Code和CheckSum的初始值
Icmp packet = new Icmp();
packet.Type = Pierce.Icmp.Icmp.eType.EchoRequest;
packet.Code = Pierce.Icmp.Icmp.eCode.NetworkUnreachable;
packet.Content=Content;
//发送信息的字节内容
byte[] icmpbyte=packet.IcmpByteArray();
host.SendTo(icmpbyte, icmpbyte.Length, SocketFlags.None, iep);
byte[] data = new byte[1024];
try
{
recv = host.ReceiveFrom(data, ref ep);
}
catch
{
host.Close();
return ifOk;
}
//接收回复
Icmp response=null;
try
{
response = new Icmp(data, recv);
}
catch
{
host.Close();
return ifOk;
}
//检验接收到的包是否出现错误
UInt16 sum=response.CalcuIcmpPack(data,recv);
if(sum!=0)
{
host.Close();
return ifOk;
}
int Identifier = BitConverter.ToInt16(response.Message, 0);
int Sequence = BitConverter.ToInt16(response.Message, 2);
string stringData = Encoding.ASCII.GetString(response.Message,
4, response.MessageSize - 4);
if( response.Type==Icmp.eType.EchoReply &&
Icmp.Identify==Identifier && Icmp.Sequence==Sequence &&
packet.Content==Content)
{
ifOk=true;
}
host.Close();
return ifOk;
}
}
}
using System.Net;
using System.Net.Sockets;
using System.Text;
using Pierce.AttributeClass;
namespace Pierce.Icmp
{
/// <summary>
/// UseIcmp :使用Icmp协议
/// </summary>
[LastModified("2005-10-13","使用Icmp协议")]
public class UseIcmp
{
private Socket host; //Socket连接
private int receiveTime; //接收时间上限
private int sendTime; //发送时间上限
/// <summary>
/// 属性,读写,接收时间上限
/// </summary>
public int ReceiveTime
{
get{return receiveTime;}
set
{
receiveTime=value;
host.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout, receiveTime);
}
}
/// <summary>
/// 属性,读写,发送时间上限
/// </summary>
public int SendTime
{
get
{
return sendTime;
}
set
{
sendTime=value;
host.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.SendTimeout, sendTime);
}
}
/// <summary>
/// 构造函数,初始化Socket
/// </summary>
public UseIcmp()
{
host = new Socket(AddressFamily.InterNetwork, SocketType.Raw,
ProtocolType.Icmp);
}
/// <summary>
/// 给指定地址,发送指定内容的Icmp包,并接受恢复
/// 如果收到恢复,那么返回True,否则,返回False
/// </summary>
/// <param name="Ip">指定Ip地址</param>
/// <param name="Content">指定发送信息</param>
/// <returns>返回值</returns>
public bool SendIcmp(string Ip,string Content)
{
bool ifOk=false; //是否成功
int recv; //接收到的字节数
//目的信息
IPEndPoint iep = new IPEndPoint(IPAddress.Parse(Ip), 0);
EndPoint ep = (EndPoint)iep;
//设置Type,Code和CheckSum的初始值
Icmp packet = new Icmp();
packet.Type = Pierce.Icmp.Icmp.eType.EchoRequest;
packet.Code = Pierce.Icmp.Icmp.eCode.NetworkUnreachable;
packet.Content=Content;
//发送信息的字节内容
byte[] icmpbyte=packet.IcmpByteArray();
host.SendTo(icmpbyte, icmpbyte.Length, SocketFlags.None, iep);
byte[] data = new byte[1024];
try
{
recv = host.ReceiveFrom(data, ref ep);
}
catch
{
host.Close();
return ifOk;
}
//接收回复
Icmp response=null;
try
{
response = new Icmp(data, recv);
}
catch
{
host.Close();
return ifOk;
}
//检验接收到的包是否出现错误
UInt16 sum=response.CalcuIcmpPack(data,recv);
if(sum!=0)
{
host.Close();
return ifOk;
}
int Identifier = BitConverter.ToInt16(response.Message, 0);
int Sequence = BitConverter.ToInt16(response.Message, 2);
string stringData = Encoding.ASCII.GetString(response.Message,
4, response.MessageSize - 4);
if( response.Type==Icmp.eType.EchoReply &&
Icmp.Identify==Identifier && Icmp.Sequence==Sequence &&
packet.Content==Content)
{
ifOk=true;
}
host.Close();
return ifOk;
}
}
}