• 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();
    }
    }
    }
  • 相关阅读:
    idea 配置 maven 项目
    idea 配置普通web项目
    idea java.lang.OutOfMemoryError: PermGen space
    idea checkout 项目
    物理机自动化装机实现
    prometheus node_exporter相关监控指标
    nginx Linux内核参数的优化
    《高性能 Go 代码工坊》中译
    docker仓库资源的地址修改
    influxdb-1.7.8(centos 7) 部署
  • 原文地址:https://www.cnblogs.com/zhuor/p/308917.html
Copyright © 2020-2023  润新知