- 本文介绍C# ping命令的实现方法,首先利用原始Socket套接字,实现ICMP协议,然后执行ping命令。最后,还可以使用C# 2.0中新增的Ping类来实现。
以下介绍C# ping命令的两种实现方法。
C# ping命令实现:利用原始Socket套接字,实现ICMP协议。
- usingSystem;
- usingSystem.Collections.Generic;
- usingSystem.Text;
- usingSystem.Net;
- usingSystem.Net.Sockets;
- namespacePingC
- {
- classping
- {
- constintSOCKET_ERROR=-1;
- constintICMP_ECHO=8;
- staticvoidMain(string[]args)
- {
- pingp=newping();
- Console.WriteLine("请输入要Ping的IP或者主机名字:");
- stringMyUrl=Console.ReadLine();
- Console.WriteLine("正在Ping"+MyUrl+"……");
- Console.Write(p.PingHost(MyUrl));
- }
- publicstringPingHost(stringhost)
- {
- //声明IPHostEntry
- IPHostEntryServerHE,fromHE;
- intnBytes=0;
- intdwStart=0,dwStop=0;
- //初始化ICMP的Socket
- Socketsocket=
- newSocket(AddressFamily.InterNetwork,SocketType.Raw,ProtocolType.Icmp);
- socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.SendTimeout,1000);
- //得到ServerEndPoint
- try
- {
- ServerHE=Dns.GetHostByName(host);
- }
- catch(Exception)
- {
- return"没有发现主机";
- }
- //把ServerIP_EndPoint转换成EndPoint
- IPEndPointipepServer=newIPEndPoint(ServerHE.AddressList[0],0);
- EndPointepServer=(ipepServer);
- //设定客户机的接收Endpoint
- fromHE=Dns.GetHostByName(Dns.GetHostName());
- IPEndPointipEndPointFrom=newIPEndPoint(fromHE.AddressList[0],0);
- EndPointEndPointFrom=(ipEndPointFrom);
- intPacketSize=0;
- IcmpPacketpacket=newIcmpPacket();
- //构建要发送的包
- packet.Type=ICMP_ECHO;//8
- packet.SubCode=0;
- packet.CheckSum=0;
- packet.Identifier=45;
- packet.SequenceNumber=0;
- intPingData=24;//sizeof(IcmpPacket)-8;
- packet.Data=newByte[PingData];
- //初始化Packet.Data
- for(inti=0;i<PingData;i++)
- {
- packet.Data[i]=(byte)'#';
- }
- //VariabletoholdthetotalPacketsize
- PacketSize=32;
- Byte[]icmp_pkt_buffer=newByte[PacketSize];
- Int32Index=0;
- //againcheckthepacketsize
- Index=Serialize(
- packet,
- icmp_pkt_buffer,
- PacketSize,
- PingData);
- //ifthereisaerrorreportit
- if(Index==-1)
- {
- return"ErrorCreatingPacket";
- }
- //convertintoaUInt16array
- //GettheHalfsizeofthePacket
- Doubledouble_length=Convert.ToDouble(Index);
- Doubledtemp=Math.Ceiling(double_length/2);
- intcksum_buffer_length=Index/2;
- //CreateaByteArray
- UInt16[]cksum_buffer=newUInt16[cksum_buffer_length];
- //CodetoinitializetheUint16array
- inticmp_header_buffer_index=0;
- for(inti=0;i<cksum_buffer_length;i++)
- {
- cksum_buffer[i]=
- BitConverter.ToUInt16(icmp_pkt_buffer,icmp_header_buffer_index);
- icmp_header_buffer_index+=2;
- }
- //Callamethodwhichwillreturnachecksum
- UInt16u_cksum=checksum(cksum_buffer,cksum_buffer_length);
- //SavethechecksumtothePacket
- packet.CheckSum=u_cksum;
- //Nowthatwehavethechecksum,serializethepacketagain
- Byte[]sendbuf=newByte[PacketSize];
- //againcheckthepacketsize
- Index=Serialize(
- packet,
- sendbuf,
- PacketSize,
- PingData);
- //ifthereisaerrorreportit
- if(Index==-1)
- {
- return"ErrorCreatingPacket";
- }
- dwStart=System.Environment.TickCount;//Starttiming
- //sendthePacketoverthesocket
- if((nBytes=socket.SendTo(sendbuf,PacketSize,0,epServer))==SOCKET_ERROR)
- {
- return"SocketError:cannotsendPacket";
- }
- //Initializethebuffers.Thereceivebufferisthesizeofthe
- //ICMPheaderplustheIPheader(20bytes)
- Byte[]ReceiveBuffer=newByte[256];
- nBytes=0;
- //Receivethebytes
- boolrecd=false;
- inttimeout=0;
- //loopforcheckingthetimeoftheserverresponding
- while(!recd)
- {
- nBytes=socket.ReceiveFrom(ReceiveBuffer,256,0,refEndPointFrom);
- if(nBytes==SOCKET_ERROR)
- {
- return"主机没有响应";
- }
- elseif(nBytes>0)
- {
- dwStop=System.Environment.TickCount-dwStart;//stoptiming
- return"Replyfrom"+epServer.ToString()+"in"
- +dwStop+"ms.Received:"+nBytes+"Bytes.";
- }
- timeout=System.Environment.TickCount-dwStart;
- if(timeout>1000)
- {
- return"超时";
- }
- }
- //closethesocket
- socket.Close();
- return"";
- }
- ///<summary>
- ///ThismethodgetthePacketandcalculatesthetotalsize
- ///ofthePackbyconvertingittobytearray
- ///</summary>
- publicstaticInt32Serialize(IcmpPacketpacket,Byte[]Buffer,
- Int32PacketSize,Int32PingData)
- {
- Int32cbReturn=0;
- //serializethestructintothearray
- intIndex=0;
- Byte[]b_type=newByte[1];
- b_type[0]=(packet.Type);
- Byte[]b_code=newByte[1];
- b_code[0]=(packet.SubCode);
- Byte[]b_cksum=BitConverter.GetBytes(packet.CheckSum);
- Byte[]b_id=BitConverter.GetBytes(packet.Identifier);
- Byte[]b_seq=BitConverter.GetBytes(packet.SequenceNumber);
- Array.Copy(b_type,0,Buffer,Index,b_type.Length);
- Index+=b_type.Length;
- Array.Copy(b_code,0,Buffer,Index,b_code.Length);
- Index+=b_code.Length;
- Array.Copy(b_cksum,0,Buffer,Index,b_cksum.Length);
- Index+=b_cksum.Length;
- Array.Copy(b_id,0,Buffer,Index,b_id.Length);
- Index+=b_id.Length;
- Array.Copy(b_seq,0,Buffer,Index,b_seq.Length);
- Index+=b_seq.Length;
- //copythedata
- Array.Copy(packet.Data,0,Buffer,Index,PingData);
- Index+=PingData;
- if(Index!=PacketSize/*sizeof(IcmpPacket)*/)
- {
- cbReturn=-1;
- returncbReturn;
- }
- cbReturn=Index;
- returncbReturn;
- }
- ///<summary>
- ///ThisMethodhasthealgorithmtomakeachecksum
- ///</summary>
- publicstaticUInt16checksum(UInt16[]buffer,intsize)
- {
- Int32cksum=0;
- intcounter;
- counter=0;
- while(size>0)
- {
- UInt16val=buffer[counter];
- cksum+=buffer[counter];
- counter+=1;
- size-=1;
- }
- cksum=(cksum>>16)+(cksum&0xffff);
- cksum+=(cksum>>16);
- return(UInt16)(~cksum);
- }
- }
- ///类结束
- ///<summary>
- ///ClassthatholdsthePackinformation
- ///</summary>
- publicclassIcmpPacket
- {
- publicByteType;//typeofmessage
- publicByteSubCode;//typeofsubcode
- publicUInt16CheckSum;//onescomplementchecksumofstruct
- publicUInt16Identifier;//identifier
- publicUInt16SequenceNumber;//sequencenumber
- publicByte[]Data;
- }//classIcmpPacket
- }
C# ping命令执行:执行ping命令
首先,我们用使用Process类,来创建独立的进程,导入System.Diagnostics,
using System.Diagnostics;
实例一个Process类,启动一个独立进程
Process p = new Process();
Process类有一个StartInfo属性,这个是ProcessStartInfo类,包括了一些属性和方法,
下面我们用到了他的几个属性:
设定程序名
p.StartInfo.FileName = "cmd.exe";
关闭Shell的使用
p.StartInfo.UseShellExecute = false;
重定向标准输入
p.StartInfo.RedirectStandardInput = true;
重定向标准输出
p.StartInfo.RedirectStandardOutput = true;
重定向错误输出
p.StartInfo.RedirectStandardError = true;
设置不显示窗口
p.StartInfo.CreateNoWindow = true;
上面几个属性的设置是比较关键的一步。
既然都设置好了那就启动进程吧,
p.Start();
输入要执行的命令,这里就是ping了,
p.StandardInput.WriteLine("ping -n 1 www.iwebtrados.com.cn");
p.StandardInput.WriteLine("exit");
从输出流获取命令执行结果,
string strRst = p.StandardOutput.ReadToEnd();
C# ping命令实现:利用c#2.0新增的Ping类
这里我写的是一个窗体程序。首先添加textbox,listbox,button控件,其中textbox录入域名或IP,listbox显示结果.
在button1_click事件键入
- privatevoidbutton1_Click(objectsender,EventArgse)
- {
- Pingp1=newPing();//只是演示,没有做错误处理
- PingReplyreply=p1.Send(this.textBox1.Text);//阻塞方式
- displayReply(reply);//显示结果
- }
- privatevoiddisplayReply(PingReplyreply)//显示结果
- {
- StringBuildersbuilder;
- if(reply.Status==IPStatus.Success)
- {
- sbuilder=newStringBuilder();
- sbuilder.Append(string.Format("Address:{0}",reply.Address.ToString()));
- sbuilder.Append(string.Format("RoundTriptime:{0}",reply.RoundtripTime));
- sbuilder.Append(string.Format("Timetolive:{0}",reply.Options.Ttl));
- sbuilder.Append(string.Format("Don'tfragment:{0}",reply.Options.DontFragment));
- sbuilder.Append(string.Format("Buffersize:{0}",reply.Buffer.Length));
- listBox1.Items.Add(sbuilder.ToString());
- }
- }
也可以做异步的处理,修改button1_click,并添加PingCompletedCallBack方法
- privatevoidbutton1_Click(objectsender,EventArgse)
- {
- Pingp1=newPing();
- p1.PingCompleted+=newPingCompletedEventHandler(this.PingCompletedCallBack);//设置PingCompleted事件处理程序
- p1.SendAsync(this.textBox1.Text,null);
- }
- privatevoidPingCompletedCallBack(objectsender,PingCompletedEventArgse)
- {
- if(e.Cancelled)
- {
- listBox1.Items.Add("PingCanncel");
- return;
- }
- if(e.Error!=null)
- {
- listBox1.Items.Add(e.Error.Message);
- return;
- }
- StringBuildersbuilder;
- PingReplyreply=e.Reply;
- if(reply.Status==IPStatus.Success)
- {
- sbuilder=newStringBuilder();
- sbuilder.Append(string.Format("Address:{0}",reply.Address.ToString()));
- sbuilder.Append(string.Format("RoundTriptime:{0}",reply.RoundtripTime));
- sbuilder.Append(string.Format("Timetolive:{0}",reply.Options.Ttl));
- sbuilder.Append(string.Format("Don'tfragment:{0}",reply.Options.DontFragment));
- sbuilder.Append(string.Format("Buffersize:{0}",reply.Buffer.Length));
- listBox1.Items.Add(sbuilder.ToString());
- }
- }
怎么样,相比1、2方式,3是不是简单的多呀。
本文来自网络小筑的博客:《c#下实现ping操作》。