سؤال

هل لدى أي شخص رمز C# مفيد لإجراء اختبار ping وتتبع المسار إلى جهاز كمبيوتر مستهدف؟أنا أبحث عن حل رمزي خالص، وليس ما أفعله الآن، وهو استدعاء برنامج ping.exe وtracert.exe وتحليل الإخراج.أود شيئا أكثر قوة.

هل كانت مفيدة؟

المحلول

على الرغم من أن مكتبة الفئة الأساسية تتضمن بينغ, ، لا يتضمن BCL أي وظيفة التتبع.

ومع ذلك، يكشف البحث السريع عن محاولتين مفتوحتين المصدر، الأولى في 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

ما يلي هو تنفيذ أفضل بكثير لـ C# tracert مما هو موجود في الإجابات الأخرى حتى الآن.

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.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 (reply.Status == IPStatus.Success)
        {
            // Success means the tracert has completed
            yield return reply.Address;
        }

        // if we ever reach here, we're finished, so break
        break;
    }
}

تتضمن المزالق التي تم إصلاحها هنا والموجودة في الإجابات الأخرى ما يلي:

  • إنه كسول.السابق:إنه يستخدم enumerable / iterator بشكل صحيح لذا لا يتعين عليك حساب الشجرة بأكملها، يمكنك التوقف عند أي نقطة عن طريق الخروج من حلقة الاستهلاك الخاصة بك.
  • maxTTL تم تنفيذها بحيث لا تدور الوظيفة إلى الأبد.
  • bufferSize الخيار الذي يتوافق مع تطبيقات ترسرت الأخرى.
  • إنها موجزة للغاية ونظيفة.إنه موجود في طريقة واحدة وهو أقصر بكثير من الخيارات الأخرى هنا.

بالنسبة للجزء ping، ألق نظرة على فئة بينغ على MSDN.

نظرًا لأني أقوم بتحسين إجابة كود Scotts أعلاه، فقد وجدت أن الحل الخاص به لا يعمل إذا كان المسار يتضاءل إلى لا شيء قبل الوصول إلى الوجهة - فهو لا يعود أبدًا.يمكن أن يكون الحل الأفضل بمسار جزئي على الأقل هو هذا (الذي قمت باختباره وهو يعمل بشكل جيد).يمكنك تغيير الرقم "20" في حلقة for إلى شيء أكبر أو أصغر أو محاولة اكتشاف ما إذا كان الأمر يستغرق وقتًا طويلاً إذا كنت تريد التحكم في عدد التكرارات بطريقة أخرى.الفضل الكامل لسكوت في الكود الأصلي - شكرًا.

    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;
        }
    }

بينغ:يمكننا استخدام Ping فئة مدمجة في .NET Framework.

إنشاء مثيل أ Ping والاشتراك في PingCompleted حدث:

Ping pingSender = new Ping();
pingSender.PingCompleted += PingCompletedCallback;

أضف رمزًا لتكوين أمر ping وإجراءه، على سبيل المثال:

string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
string who = "www.google.com";
AutoResetEvent waiter = new AutoResetEvent(false);
int timeout = 12000;

PingOptions options = new PingOptions(64, true);

pingSender.SendAsync(who, timeout, buffer, options, waiter);

أضف PingCompletedEventHandler:

public static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
    ... Do stuff here
}

تفريغ التعليمات البرمجية لمثال عمل كامل، بناءً على مثال MSDN:

public static void Main(string[] args)
{
    string who = "www.google.com";
    AutoResetEvent waiter = new AutoResetEvent(false);

    Ping pingSender = new Ping();

    // When the PingCompleted event is raised,
    // the PingCompletedCallback method is called.
    pingSender.PingCompleted += PingCompletedCallback;

    // Create a buffer of 32 bytes of data to be transmitted.
    string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    byte[] buffer = Encoding.ASCII.GetBytes(data);

    // Wait 12 seconds for a reply.
    int timeout = 12000;

    // Set options for transmission:
    // The data can go through 64 gateways or routers
    // before it is destroyed, and the data packet
    // cannot be fragmented.
    PingOptions options = new PingOptions(64, true);

    Console.WriteLine("Time to live: {0}", options.Ttl);
    Console.WriteLine("Don't fragment: {0}", options.DontFragment);

    // Send the ping asynchronously.
    // Use the waiter as the user token.
    // When the callback completes, it can wake up this thread.
    pingSender.SendAsync(who, timeout, buffer, options, waiter);

    // Prevent this example application from ending.
    // A real application should do something useful
    // when possible.
    waiter.WaitOne();
    Console.WriteLine("Ping example completed.");
}

public static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
    // If the operation was canceled, display a message to the user.
    if (e.Cancelled)
    {
        Console.WriteLine("Ping canceled.");

        // Let the main thread resume. 
        // UserToken is the AutoResetEvent object that the main thread 
        // is waiting for.
        ((AutoResetEvent)e.UserState).Set();
    }

    // If an error occurred, display the exception to the user.
    if (e.Error != null)
    {
        Console.WriteLine("Ping failed:");
        Console.WriteLine(e.Error.ToString());

        // Let the main thread resume. 
        ((AutoResetEvent)e.UserState).Set();
    }

    Console.WriteLine($"Roundtrip Time: {e.Reply.RoundtripTime}");

    // Let the main thread resume.
    ((AutoResetEvent)e.UserState).Set();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top