c#多线程ping实战
来源:互联网 发布:剑灵召唤卡刀宏数据 编辑:程序博客网 时间:2024/04/29 08:02
[上一篇][本讨论区][下一篇][同主题阅读]
发信人: 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]
[上一篇][本讨论区][下一篇][同主题阅读]
- c#多线程ping实战
- 【实战】ping
- C#多线程编程实例实战
- C#多线程编程实例实战
- C#多线程编程实例实战
- C#多线程编程实例实战
- C#多线程编程实例实战
- C#多线程编程实例实战
- C#多线程编程实例实战
- C#多线程编程实例实战
- C#多线程编程实例实战
- C#多线程编程实例实战
- C#多线程编程实例实战
- c# ping
- c# ping
- C# Ping
- C#多线程编程实例实战(2)
- C#多线程编程实例实战1
- 最困的一天的开始
- 检测你的程序是否运行在虚拟机(VMware)
- [原创]批量表结构提取和批量建表
- [原创]批量数据上传(access到sql server。sql server到sql server)
- 看云
- c#多线程ping实战
- 终于找到我喜欢的那首歌了:《一生别无所求》
- 基本养老保险存在的问题与对策
- Java与C及C++的区别
- 反手执刃
- 权限系统
- 农村养老保险制度亟待完善
- sql table
- 用正确方法写出质量好的软件的75条体会