TraceRoute和C#中的Ping
有没有人有C#代码方便做ping和跟踪路由到目标计算机? 我正在寻找一个纯粹的代码解决scheme,而不是我现在正在做什么,这是调用ping.exe和tracert.exe程序并parsing输出。 我想要更强大的东西。
虽然基类库包含Ping ,但BCL不包含任何tracertfunction。
然而,快速search揭示了两个开源尝试,第一个在C#中第二个在C ++中:
鉴于我今天不得不写一个TraceRoute类,我想我可能会分享源代码。
using System.Collections.Generic; using System.Net.NetworkInformation; using System.Text; using System.Net; namespace Answer { public class TraceRoute { private const string Data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; public static IEnumerable<IPAddress> GetTraceRoute(string hostNameOrAddress) { return GetTraceRoute(hostNameOrAddress, 1); } private static IEnumerable<IPAddress> GetTraceRoute(string hostNameOrAddress, int ttl) { Ping pinger = new Ping(); PingOptions pingerOptions = new PingOptions(ttl, true); int timeout = 10000; byte[] buffer = Encoding.ASCII.GetBytes(Data); PingReply reply = default(PingReply); reply = pinger.Send(hostNameOrAddress, timeout, buffer, pingerOptions); List<IPAddress> result = new List<IPAddress>(); if (reply.Status == IPStatus.Success) { result.Add(reply.Address); } else if (reply.Status == IPStatus.TtlExpired || reply.Status == IPStatus.TimedOut) { //add the currently returned address if an address was found with this TTL if (reply.Status == IPStatus.TtlExpired) result.Add(reply.Address); //recurse to get the next address... IEnumerable<IPAddress> tempResult = default(IEnumerable<IPAddress>); tempResult = GetTraceRoute(hostNameOrAddress, ttl + 1); result.AddRange(tempResult); } else { //failure } return result; } } }
而任何想要/需要它的VB版本
Public Class TraceRoute Private Const Data As String = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" Public Shared Function GetTraceRoute(ByVal hostNameOrAddress As String) As IEnumerable(Of IPAddress) Return GetTraceRoute(hostNameOrAddress, 1) End Function Private Shared Function GetTraceRoute(ByVal hostNameOrAddress As String, ByVal ttl As Integer) As IEnumerable(Of IPAddress) Dim pinger As Ping = New Ping Dim pingerOptions As PingOptions = New PingOptions(ttl, True) Dim timeout As Integer = 10000 Dim buffer() As Byte = Encoding.ASCII.GetBytes(Data) Dim reply As PingReply reply = pinger.Send(hostNameOrAddress, timeout, buffer, pingerOptions) Dim result As List(Of IPAddress) = New List(Of IPAddress) If reply.Status = IPStatus.Success Then result.Add(reply.Address) ElseIf reply.Status = IPStatus.TtlExpired Then 'add the currently returned address result.Add(reply.Address) 'recurse to get the next address... Dim tempResult As IEnumerable(Of IPAddress) tempResult = GetTraceRoute(hostNameOrAddress, ttl + 1) result.AddRange(tempResult) Else 'failure End If Return result End Function End Class
对于ping部分,请查看MSDN上的Ping类 。
这里是如何实现traceoute http://coding.infoconex.com/post/2009/01/C-Traceroute-using-net-framework.aspx
另一个如何实现Ping。 http://coding.infoconex.com/post/2009/01/C-Ping-and-Traceroute.aspx
上面重复了与windows ping和traceroute相同的行为,实现起来非常简单。
看一下 –
http://www.codeproject.com/KB/IP/Tracert-ping.aspx
如果你能负担得起,Dart联网小部件相当不错:
http://www.dart.com/ctl_tracenet.aspx
这里还有一个免费的实现:
http://www.digigrupp.com/ping/和这里http://www.mltek.co.uk/traceclass.aspx
接下来是迄今为止其他答案中存在的比tracert
更好的C#实现。
public static IEnumerable<IPAddress> GetTraceRoute(string hostname) { // following are the defaults for the "traceroute" command in unix. const int timeout = 10000; const int maxTTL = 30; const int bufferSize = 32; byte[] buffer = new byte[bufferSize]; new Random().NextBytes(buffer); Ping pinger = new Ping(); for (int ttl = 1; ttl <= maxTTL; ttl++) { PingOptions options = new PingOptions(ttl, true); PingReply reply = pinger.Send(hostname, timeout, buffer, options); if (reply.Status == IPStatus.Success) { // Success means the tracert has completed yield return reply.Address; break; } if (reply.Status == IPStatus.TtlExpired) { // TtlExpired means we've found an address, but there are more addresses yield return reply.Address; continue; } if (reply.Status == IPStatus.TimedOut) { // TimedOut means this ttl is no good, we should continue searching continue; } // if we reach here, it's a status we don't recognize and we should exit. break; } }
其他答案中存在的固定缺点包括:
- 这很懒。 例如:它正确地使用了enumerable / iterator,所以不必计算整个树,你可以在任何时候停止你自己的消费循环。
-
maxTTL
实现,所以函数不会永远旋转。 - 与其他tracert实现一致的
bufferSize
选项。 - 这是非常简洁和干净。 它包含在一个单一的方法中,比这里的其他选项短得多。
我将开始在System.Net命名空间中查找它们
这个解决了ping问题,而不使用第三方
http://www.aspnettutorials.com/tutorials/network/net-ping-aspnet2-csharp.aspx
正如上面对Scotts代码的回答所做的改进,我发现如果路线在到达目的地之前就没有任何变化,他的解决scheme就无法工作 – 它永远不会返回。 至less有一个部分路线的更好的解决scheme可能是(我已经testing,它运作良好)。 您可以将for循环中的“20”更改为更大或更小的值,或者尝试检测是否需要太长的时间才能以其他方式控制迭代次数。 感谢Scott对原始代码的完全信任。
using System.Collections.Generic; using System.Net.NetworkInformation; using System.Text; using System.Net; ... public static void TraceRoute(string hostNameOrAddress) { for (int i = 1; i < 20; i++) { IPAddress ip = GetTraceRoute(hostNameOrAddress, i); if(ip == null) { break; } Console.WriteLine(ip.ToString()); } } private static IPAddress GetTraceRoute(string hostNameOrAddress, int ttl) { const string Data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; Ping pinger = new Ping(); PingOptions pingerOptions = new PingOptions(ttl, true); int timeout = 10000; byte[] buffer = Encoding.ASCII.GetBytes(Data); PingReply reply = default(PingReply); reply = pinger.Send(hostNameOrAddress, timeout, buffer, pingerOptions); List<IPAddress> result = new List<IPAddress>(); if (reply.Status == IPStatus.Success || reply.Status == IPStatus.TtlExpired) { return reply.Address; } else { return null; } }