c#多线程ping实战

来源:互联网 发布:剑灵召唤卡刀宏数据 编辑:程序博客网 时间:2024/04/29 08:02
瀚海星云 -- 文章阅读 [讨论区: DotNet]
[上一篇][本讨论区][下一篇][同主题阅读]
发信人: SharperC.bbs@bbs.sjtu.edu.cn (Wind 疾风步 Walker), 信区: DotNet标  题: 【原创】c#多线程ping实战发信站: 饮水思源 (Thu May  5 14:03:22 2005)转信站: USTC!bbsnews.sdu!SJTU终于还是弄出来了关于发ICMP包进行ping,以检测网络各主机的连接状况网上已有相关的C#程序但是给出的代码是不能正常工作的,原因在于阻塞式socket的sendto方法,当目标机不存在时,会挂起ping线程第二,多线程下,对于收到的packet没有检查sequence,这样就可能把ping主机a的ECHO当作ping主机b的ECHO,起不到监视指定网络连接的作用参考C/C++中的socket编程,作了如下改动,1)通过SetSocketOption函数设置发送、接收超时2)对于收到的字节流,提取其中的sequence,并与发送该包的sequence作比较,以判断是否对应;具体在我的程序中,是添加了public UInt16 GetSequenceNum(Byte[] buffer)函数。测试该程序,(ping函数返回-1表示链路不通,0表示通畅)开了8个线程ping,可以正常工作,完整代码如下:【附C#实现ping的其他方法及优缺点】using System;using System.Net;using System.Net.Sockets;using System.Threading;namespace pingConsole{    /// <summary>    /// Class1 的摘要说明。    /// </summary>    class Class1    {        /// <summary>        /// 应用程序的主入口点。        /// </summary>        [STAThread]        static void Main(string[] args)        {            //            // TODO: 在此处添加代码以启动应用程序            //            string[] target1 = {"127.0.0.1"};            string[] target2 = {"10.253.0.100"};//          string[] target3 = {"127.0.0.1"};//          string[] target4 = {"10.254.0.100"};//          string[] target5 = {"127.0.0.1"};//          string[] target6 = {"10.254.0.100"};            ThreadPing tp1, tp2, tp3, tp4, tp5, tp6, tp7, tp8;            tp1 = new ThreadPing(target1, 400);            tp2 = new ThreadPing(target2, 400);            tp3 = new ThreadPing(target1, 400);            tp4 = new ThreadPing(target2, 400);            tp5 = new ThreadPing(target1, 400);            tp6 = new ThreadPing(target2, 400);            tp7 = new ThreadPing(target1, 400);            tp8 = new ThreadPing(target2, 400);            new Thread(new ThreadStart(tp1.PingWorker)).Start();            new Thread(new ThreadStart(tp2.PingWorker)).Start();            new Thread(new ThreadStart(tp3.PingWorker)).Start();            new Thread(new ThreadStart(tp4.PingWorker)).Start();            new Thread(new ThreadStart(tp5.PingWorker)).Start();            new Thread(new ThreadStart(tp6.PingWorker)).Start();            new Thread(new ThreadStart(tp7.PingWorker)).Start();            new Thread(new ThreadStart(tp8.PingWorker)).Start();        }    }    public class ThreadPing     {        private string[] _target;        private int _timeOutVal;        public ThreadPing(string[] target, int timeOutVal)        {            _target = target;            _timeOutVal = timeOutVal;        }        public void PingWorker()        {            for(;;)            {                int retval= IcmpPacket.PingHost(_target, _timeOutVal);                Console.WriteLine(_target[0] + " status:" + retval.ToString());                Thread.Sleep(500);            }        }    }    public class IcmpPacket    {        private Byte _type;        private Byte _subCode;        private UInt16 _checkSum;        private UInt16 _identifier;        private UInt16 _sequenceNumber;        private Byte[] _data;        private static UInt16 UInt16_Seq = 0;        public IcmpPacket(Byte type, Byte subCode, UInt16 checkSum, UInt16 identifier,            UInt16 sequenceNumber, int dataSize)        {            _type = type;            _subCode = subCode;            _checkSum = checkSum;            _identifier = identifier;            _sequenceNumber = sequenceNumber;            _data = new Byte[dataSize];            for (int i=0; i<dataSize; i++)            {                _data[i] = (Byte) '#';            }        }        public UInt16 CheckSum        {            get            {                return _checkSum;            }            set            {                _checkSum = value;            }        }        public int ConverToByte(Byte[] buffer)        {            Byte[] b_type = new Byte[1] {_type};            Byte[] b_subCode = new Byte[1]{_subCode};            Byte[] b_cksum = BitConverter.GetBytes(_checkSum);            Byte[] b_id = BitConverter.GetBytes(_identifier);            Byte[] b_seq = BitConverter.GetBytes(_sequenceNumber);            int i = 0;            Array.Copy(b_type, 0, buffer, i, b_type.Length);            i += b_type.Length;            Array.Copy(b_subCode, 0, buffer, i, b_subCode.Length);            i += b_subCode.Length;            Array.Copy(b_cksum, 0, buffer, i, b_cksum.Length);            i += b_cksum.Length;            Array.Copy(b_id, 0, buffer, i, b_id.Length);            i += b_id.Length;            Array.Copy(b_seq, 0, buffer, i, b_seq.Length);            i += b_seq.Length;            Array.Copy(_data, 0, buffer, i, _data.Length);            i += _data.Length;            return i;        }        public UInt16 GetSequenceNum(Byte[] buffer)        {            UInt16 i_seq = 0;            try            {                 i_seq = BitConverter.ToUInt16(buffer, 26);            }            catch(Exception ex)            {                Console.WriteLine(ex.ToString());            }                            return i_seq;        }        public static UInt16 SumofCheck (UInt16[] buffer)        {            int sum = 0;            for (int i=0; i<buffer.Length; i++)                sum += (int)buffer[i];            sum = (sum >> 16) + (sum & 0xffff);            sum += (sum >> 16);            return (UInt16) (~sum);        }        public static int PingHost(string[] hostclient, int timeOutVal)        {            const int ICMP_ECHO = 8;            const int PING_ERR = -1;            const int TIME_OUT = 200;            int retval = 0;            Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);            sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, TIME_OUT);            sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, TIME_OUT);            IPHostEntry hostInfo = null;            try            {                IPAddress ipaddr = IPAddress.Parse(hostclient[0]);                hostInfo = Dns.GetHostByName(hostclient[0]);            }            catch(Exception)            {                retval = PING_ERR;                goto exit;            }            EndPoint hostPoint = (EndPoint) new IPEndPoint(hostInfo.AddressList[0], 0);            IPHostEntry clientInfo = null;            try            {                if (hostclient.Length > 1)                    clientInfo = Dns.GetHostByAddress(hostclient[1]);                else                    clientInfo = Dns.GetHostByName(Dns.GetHostName());            }            catch (Exception)            {                retval = PING_ERR;                goto exit;            }            EndPoint clientPoint = (EndPoint) new IPEndPoint(clientInfo.AddressList[0], 0);            int dataSize = 32;            int packetSize = dataSize + 8;            IcmpPacket packet = new IcmpPacket(ICMP_ECHO, 0, 0, 45, UInt16_Seq++, dataSize);            Byte[] buffer = new Byte[packetSize];            int index = packet.ConverToByte(buffer);            if (index != packetSize)            {                retval = PING_ERR;                goto exit;            }            int count = (int)Math.Ceiling( (Double)index/2);            UInt16[] buffer2 = new UInt16[count];            index = 0;            for (int i=0; i<count; i++)            {                buffer2[i] = BitConverter.ToUInt16(buffer, index);                index += 2;            }            packet.CheckSum = IcmpPacket.SumofCheck(buffer2);            Byte[] sendData = new Byte[packetSize];            index = packet.ConverToByte(sendData);            if (index != packetSize)            {                retval = PING_ERR;                goto exit;            }            for (int i=0; i<5; i++)            {                int nBytes = 0;                int startTime = Environment.TickCount;                try                {                    if ((nBytes = sock.SendTo(sendData, packetSize, SocketFlags.None, (EndPoint)hostPoint)) == -1)                    {                        retval = PING_ERR;                        goto exit;                    }//                  Console.WriteLine(nBytes.ToString());                }                catch(Exception ex)                {                    Console.WriteLine("Send time out");                    return -1;                }                Byte[] receiveData = new Byte[256];                nBytes = 0;                int timeout = 0;                int timeConsume = 0;                while (true)                {                    try                    {                        nBytes = sock.ReceiveFrom(receiveData, 256, SocketFlags.None, ref (EndPoint)clientPoint);                        if (nBytes > 0)                        {                            if (packet._sequenceNumber == packet.GetSequenceNum(receiveData))                            {                                retval = 0;                                goto exit;                            }                        }                    }                    catch(Exception ex)                    {                        Console.WriteLine(ex.ToString());                        return -1;                    }                    if (nBytes == -1)                    {                        retval = PING_ERR;                        goto exit;                    }                    else if (nBytes > 0)                    {                        timeConsume = System.Environment.TickCount - startTime;                        retval = timeConsume;                    }                    timeout = System.Environment.TickCount - startTime;                    if (timeout > timeOutVal)                    {                        retval = PING_ERR;                        goto exit;                    }                                }            }exit:       sock.Close();            return retval;                    }    }}【C#实现ping的其他方法】 1。调用cmd这个比较简单,调用系统的command中ping.exe输入输出重定向,以获取结果字符流,并进行分析但是由于操作中每次ping需要开关进程操作,运行时间长后系统资源不足,最终会出现无法进一步开启cmd的局面2。用c/c++写dll,c#调用原理也是通过ICMP包收发,只是存在指针,对包头的数据结构操作比较方便--   /  _.-.  .-/,___|  _-| / / //|_/  |    `-._   `-'  f/ |       / __/ /__  / |__/ |        `-'    ※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 211.80.41.99]

[上一篇][本讨论区][下一篇][同主题阅读]
原创粉丝点击