C#pingコマンドの実装方法:Pingクラスの使用


本稿では,C#pingコマンドの実装方法を紹介し,まず元のSocketソケットを用いてICMPプロトコルを実装し,pingコマンドを実行する.最後に、C#2.0に追加されたPingクラスを使用して実装することもできます.
C#pingコマンドの2つの実装方法について説明します.
C#pingコマンド実装:元のSocketソケットを使用してICMPプロトコルを実装します.

 
  1. usingSystem;
  2. usingSystem.Collections.Generic;
  3. usingSystem.Text;
  4. usingSystem.Net;
  5. usingSystem.Net.Sockets;
  6. namespacePingC
  7. {
  8. classping
  9. {
  10. constintSOCKET_ERROR=-1;
  11. constintICMP_ECHO=8;
  12. staticvoidMain(string[]args)
  13. {
  14. pingp=newping();
  15. Console.WriteLine(" Ping IP :");
  16. stringMyUrl=Console.ReadLine();
  17. Console.WriteLine(" Ping"+MyUrl+"……");
  18. Console.Write(p.PingHost(MyUrl));
  19. }
  20. publicstringPingHost(stringhost)
  21. {
  22. // IPHostEntry
  23. IPHostEntryServerHE,fromHE;
  24. intnBytes=0;
  25. intdwStart=0,dwStop=0;
  26. // ICMP Socket
  27. Socketsocket=
  28. newSocket(AddressFamily.InterNetwork,SocketType.Raw,ProtocolType.Icmp);
  29. socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.SendTimeout,1000);
  30. // ServerEndPoint
  31. try
  32. {
  33. ServerHE=Dns.GetHostByName(host);
  34. }
  35. catch(Exception)
  36. {
  37. return" ";
  38. }
  39. // ServerIP_EndPoint EndPoint
  40. IPEndPointipepServer=newIPEndPoint(ServerHE.AddressList[0],0);
  41. EndPointepServer=(ipepServer);
  42. // Endpoint
  43. fromHE=Dns.GetHostByName(Dns.GetHostName());
  44. IPEndPointipEndPointFrom=newIPEndPoint(fromHE.AddressList[0],0);
  45. EndPointEndPointFrom=(ipEndPointFrom);
  46. intPacketSize=0;
  47. IcmpPacketpacket=newIcmpPacket();
  48. //
  49. packet.Type=ICMP_ECHO;//8
  50. packet.SubCode=0;
  51. packet.CheckSum=0;
  52. packet.Identifier=45;
  53. packet.SequenceNumber=0;
  54. intPingData=24;//sizeof(IcmpPacket)-8;
  55. packet.Data=newByte[PingData];
  56. // Packet.Data
  57. for(inti=0;i<PingData;i++)
  58. {
  59. packet.Data[i]=(byte)'#';
  60. }
  61. //VariabletoholdthetotalPacketsize
  62. PacketSize=32;
  63. Byte[]icmp_pkt_buffer=newByte[PacketSize];
  64. Int32Index=0;
  65. //againcheckthepacketsize
  66. Index=Serialize(
  67. packet,
  68. icmp_pkt_buffer,
  69. PacketSize,
  70. PingData);
  71. //ifthereisaerrorreportit
  72. if(Index==-1)
  73. {
  74. return"ErrorCreatingPacket";
  75. }
  76. //convertintoaUInt16array
  77. //GettheHalfsizeofthePacket
  78. Doubledouble_length=Convert.ToDouble(Index);
  79. Doubledtemp=Math.Ceiling(double_length/2);
  80. intcksum_buffer_length=Index/2;
  81. //CreateaByteArray
  82. UInt16[]cksum_buffer=newUInt16[cksum_buffer_length];
  83. //CodetoinitializetheUint16array
  84. inticmp_header_buffer_index=0;
  85. for(inti=0;i<cksum_buffer_length;i++)
  86. {
  87. cksum_buffer[i]=
  88. BitConverter.ToUInt16(icmp_pkt_buffer,icmp_header_buffer_index);
  89. icmp_header_buffer_index+=2;
  90. }
  91. //Callamethodwhichwillreturnachecksum
  92. UInt16u_cksum=checksum(cksum_buffer,cksum_buffer_length);
  93. //SavethechecksumtothePacket
  94. packet.CheckSum=u_cksum;
  95. //Nowthatwehavethechecksum,serializethepacketagain
  96. Byte[]sendbuf=newByte[PacketSize];
  97. //againcheckthepacketsize
  98. Index=Serialize(
  99. packet,
  100. sendbuf,
  101. PacketSize,
  102. PingData);
  103. //ifthereisaerrorreportit
  104. if(Index==-1)
  105. {
  106. return"ErrorCreatingPacket";
  107. }
  108. dwStart=System.Environment.TickCount;//Starttiming
  109. //sendthePacketoverthesocket
  110. if((nBytes=socket.SendTo(sendbuf,PacketSize,0,epServer))==SOCKET_ERROR)
  111. {
  112. return"SocketError:cannotsendPacket";
  113. }
  114. //Initializethebuffers.Thereceivebufferisthesizeofthe
  115. //ICMPheaderplustheIPheader(20bytes)
  116. Byte[]ReceiveBuffer=newByte[256];
  117. nBytes=0;
  118. //Receivethebytes
  119. boolrecd=false;
  120. inttimeout=0;
  121. //loopforcheckingthetimeoftheserverresponding
  122. while(!recd)
  123. {
  124. nBytes=socket.ReceiveFrom(ReceiveBuffer,256,0,refEndPointFrom);
  125. if(nBytes==SOCKET_ERROR)
  126. {
  127. return" ";
  128. }
  129. elseif(nBytes>0)
  130. {
  131. dwStop=System.Environment.TickCount-dwStart;//stoptiming
  132. return"Replyfrom"+epServer.ToString()+"in"
  133. +dwStop+"ms.Received:"+nBytes+"Bytes.";
  134. }
  135. timeout=System.Environment.TickCount-dwStart;
  136. if(timeout>1000)
  137. {
  138. return" ";
  139. }
  140. }
  141. //closethesocket
  142. socket.Close();
  143. return"";
  144. }
  145. ///<summary>
  146. ///ThismethodgetthePacketandcalculatesthetotalsize
  147. ///ofthePackbyconvertingittobytearray
  148. ///</summary>
  149. publicstaticInt32Serialize(IcmpPacketpacket,Byte[]Buffer,
  150. Int32PacketSize,Int32PingData)
  151. {
  152. Int32cbReturn=0;
  153. //serializethestructintothearray
  154. intIndex=0;
  155. Byte[]b_type=newByte[1];
  156. b_type[0]=(packet.Type);
  157. Byte[]b_code=newByte[1];
  158. b_code[0]=(packet.SubCode);
  159. Byte[]b_cksum=BitConverter.GetBytes(packet.CheckSum);
  160. Byte[]b_id=BitConverter.GetBytes(packet.Identifier);
  161. Byte[]b_seq=BitConverter.GetBytes(packet.SequenceNumber);
  162. Array.Copy(b_type,0,Buffer,Index,b_type.Length);
  163. Index+=b_type.Length;
  164. Array.Copy(b_code,0,Buffer,Index,b_code.Length);
  165. Index+=b_code.Length;
  166. Array.Copy(b_cksum,0,Buffer,Index,b_cksum.Length);
  167. Index+=b_cksum.Length;
  168. Array.Copy(b_id,0,Buffer,Index,b_id.Length);
  169. Index+=b_id.Length;
  170. Array.Copy(b_seq,0,Buffer,Index,b_seq.Length);
  171. Index+=b_seq.Length;
  172. //copythedata
  173. Array.Copy(packet.Data,0,Buffer,Index,PingData);
  174. Index+=PingData;
  175. if(Index!=PacketSize/*sizeof(IcmpPacket)*/)
  176. {
  177. cbReturn=-1;
  178. returncbReturn;
  179. }
  180. cbReturn=Index;
  181. returncbReturn;
  182. }
  183. ///<summary>
  184. ///ThisMethodhasthealgorithmtomakeachecksum
  185. ///</summary>
  186. publicstaticUInt16checksum(UInt16[]buffer,intsize)
  187. {
  188. Int32cksum=0;
  189. intcounter;
  190. counter=0;
  191. while(size>0)
  192. {
  193. UInt16val=buffer[counter];
  194. cksum+=buffer[counter];
  195. counter+=1;
  196. size-=1;
  197. }
  198. cksum=(cksum>>16)+(cksum&0xffff);
  199. cksum+=(cksum>>16);
  200. return(UInt16)(~cksum);
  201. }
  202. }
  203. ///
  204. ///<summary>
  205. ///ClassthatholdsthePackinformation
  206. ///</summary>
  207. publicclassIcmpPacket
  208. {
  209. publicByteType;//typeofmessage
  210. publicByteSubCode;//typeofsubcode
  211. publicUInt16CheckSum;//onescomplementchecksumofstruct
  212. publicUInt16Identifier;//identifier
  213. publicUInt16SequenceNumber;//sequencenumber
  214. publicByte[]Data;
  215. }//classIcmpPacket
  216. }

C#pingコマンド実行:pingコマンド実行
まず、Processクラスを使用して、独立したプロセスを作成し、Systemをインポートします.Diagnostics,
using System.Diagnostics;
インスタンスプロセスクラス、独立したプロセスの開始
Process p = new Process();
Processクラスには、いくつかの属性とメソッドを含むProcessStartInfoクラスのStartInfo属性があります.
次に、彼のいくつかのプロパティを使用します.
プログラム名の設定
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は結果を表示する.
button 1_clickイベント入力

 
  1. privatevoidbutton1_Click(objectsender,EventArgse)
  2. {
  3. Pingp1=newPing();// ,
  4. PingReplyreply=p1.Send(this.textBox1.Text);//
  5. displayReply(reply);//
  6. }
  7. privatevoiddisplayReply(PingReplyreply)//
  8. {
  9. StringBuildersbuilder;
  10. if(reply.Status==IPStatus.Success)
  11. {
  12. sbuilder=newStringBuilder();
  13. sbuilder.Append(string.Format("Address:{0}",reply.Address.ToString()));
  14. sbuilder.Append(string.Format("RoundTriptime:{0}",reply.RoundtripTime));
  15. sbuilder.Append(string.Format("Timetolive:{0}",reply.Options.Ttl));
  16. sbuilder.Append(string.Format("Don'tfragment:{0}",reply.Options.DontFragment));
  17. sbuilder.Append(string.Format("Buffersize:{0}",reply.Buffer.Length));
  18. listBox1.Items.Add(sbuilder.ToString());
  19. }
  20. }

非同期の処理をしてbutton 1_を修正することもできます.Click、PingCompletedCallBackメソッドを追加

 
  1. privatevoidbutton1_Click(objectsender,EventArgse)
  2. {
  3. Pingp1=newPing();
  4. p1.PingCompleted+=newPingCompletedEventHandler(this.PingCompletedCallBack);// PingCompleted
  5. p1.SendAsync(this.textBox1.Text,null);
  6. }
  7. privatevoidPingCompletedCallBack(objectsender,PingCompletedEventArgse)
  8. {
  9. if(e.Cancelled)
  10. {
  11. listBox1.Items.Add("PingCanncel");
  12. return;
  13. }
  14. if(e.Error!=null)
  15. {
  16. listBox1.Items.Add(e.Error.Message);
  17. return;
  18. }
  19. StringBuildersbuilder;
  20. PingReplyreply=e.Reply;
  21. if(reply.Status==IPStatus.Success)
  22. {
  23. sbuilder=newStringBuilder();
  24. sbuilder.Append(string.Format("Address:{0}",reply.Address.ToString()));
  25. sbuilder.Append(string.Format("RoundTriptime:{0}",reply.RoundtripTime));
  26. sbuilder.Append(string.Format("Timetolive:{0}",reply.Options.Ttl));
  27. sbuilder.Append(string.Format("Don'tfragment:{0}",reply.Options.DontFragment));
  28. sbuilder.Append(string.Format("Buffersize:{0}",reply.Buffer.Length));
  29. listBox1.Items.Add(sbuilder.ToString());
  30. }
  31. }

どうですか、1、2方式に比べて、3は簡単なほうが多いのではないでしょうか.
本文はネット小築のブログ:『c#の下でping操作を実現する』から来た.