2017-02-03 4 views
3

Ich versuche eine App zu erstellen, die ein Netzwerk nach ARP-Anforderungen scannt und alle vorhandenen Netzwerkgeräte auflistet. Zur Zeit verwende ich SharpPcap und PacketDoNet.Ausnahmebedingung beim Auflösen von Hostname

Beim Auflösen des Hostnamens gemäß der angegebenen IP, bekomme ich eine SocketException beim Auflösen eines "unbekannten" Hosts. Also habe ich das in einen Versuch/Fang gesteckt. Da ich denke, das ist ein schlechter Stil (um Ausnahmen zu ignorieren), suche ich nach einer anderen Lösung. Hier

ist ein Code:

// Button for scanning the network 
private void btnStartScanningForClients_Click(object sender, RoutedEventArgs e) 
{ 
    // Check for correct interface 
    // [...] 

    // Start scanning process 
    if (!this.netWorkItOut.Startet) 
    { 
     // Dis-/Enable visual controls 
     // [...] 

     // Start scanning 
     var index = this.cbNetworkInterface.SelectedIndex 
     this.netWorkItOut.StartDevice(index); 
     this.netWorkItOut.Scanner.StartScanningNetwork(resolveHostnames); 
    } 
} 

Dies ist das Controlling-Objekt, das den Scanner hält, übernimmt für Veranstaltungen, nimmt die Pakete und legt sie in eine Warteschlange

public void StartDevice(int deviceIndex) 
{ 
    this.Startet = true; 
    // [...] 
    this.Device = WinPcapDeviceList.Instance[deviceIndex]; 

    // Activate Scanner 
    this.Scanner = new Scanner(this.DeviceInfo); 

    // Subscribe Events 
    // [...] 

    this.Device.Open(DeviceMode.Promiscuous, 1); 
    this.Device.Filter = "(arp || ip || ip6)"; 

    this.Device.OnPacketArrival += device_OnPacketArrival; 
    this.Device.StartCapture(); 
} 

private void device_OnPacketArrival(object sender, CaptureEventArgs e) 
{ 
    //PacketDoNet 
    Packet packet; 

    try 
    { packet = Packet.ParsePacket(LinkLayers.Ethernet, e.Packet.Data); } 
    catch (Exception) 
    { return; } 

    if (packet is EthernetPacket) 
    { 
     var arp = ARPPacket.GetEncapsulated(packet); 

     if (arp != null) 
     { 
      if (this.Scanner.Started) 
      { 
       lock (this.Scanner.PacketQueueARP) 
       { 
        this.Scanner.PacketQueueARP.Add(arp); 
       } 
      } 
     } 
    } 
} 

Dies ist Objekt- und Scannerklasse steuern Die Scanner-Klasse arbeitet, um die ARP-Anfragen und löst den Hostnamen

public void StartScanningNetwork(bool resolveHostnames) 
{ 
    // [...] 
    this.ResolveHostnames = resolveHostnames; 

    // start worker to listen for ARP packets 
    this.workerARP = new Thread(WorkerARP); 
    this.workerARP.Name = "Scanner thread (ARP)"; 
    this.workerARP.Start(); 

    this.Started = true; 
} 

private void WorkerARP() 
{ 
    List<IPAddress> processedIps = new List<IPAddress>(); 

    // copy packets from storage queue to thread queue for processing 
    while (Started) 
    { 
     // [...] 

     if (this.threadQueueARP.Count > 0) 
     { 
      foreach (var packet in this.threadQueueARP) 
      { 
       // [...] 

       if (!processedIps.Contains(ip)) 
       { 
        // [...] 

        if (this.ResolveHostnames) 
        { 
         var resolveHostnamesTask = Task.Factory.StartNew(ResolveHostnamesWorker, ip); 
        } 
       } 
       // [...] 
      } 

      // [...] 
     } 
     // [...] 
    } 

} 

private void ResolveHostnamesWorker(object data) 
{ 
    if (data is IPAddress) 
    { 
     var ip = (IPAddress)data; 
     var hostname = ""; 

     try 
     { 
      hostname = Dns.GetHostEntry(ip).HostName; 
     } 
     catch { } 

     // Raise Event for hostname resolved 
    } 
} 

Es ist alles über die Linie hostname = Dns.GetHostEntry(ip).HostName

Also: Wie kann ich ein try/catch vermeiden zu verwenden, wenn eine HostEntry über Dns.GetHostEntry Lösung()? Gibt es eine Funktion, die nur null zurückgibt, wenn es keinen bekannten Host gibt?

Vielen Dank im Voraus!

Antwort

1

Soweit ich weiß gibt es keine Methode wie TryGetHostName(), die keine Ausnahme auslösen würde.

Aber meiner Meinung nach ist es lesbar, Ausnahmen so weit zu fangen, wie Sie es erwarten. So sollten Sie beschränken Ausnahmen auf diejenigen fangen Sie erwarten:

private void ResolveHostnamesWorker(object data) 
{ 
    if (data is IPAddress) 
    { 
     var ip = (IPAddress)data; 
     var hostname = ""; 

     try 
     { 
      hostname = Dns.GetHostEntry(ip).HostName; 
     } 
     catch(SocketException socketException) 
     { 
      // maybe limit handling based on data in socketException and 
      // call throw; to rethrow exception if not the expected one 
     } 

    // Raise Event for hostname resolved 
} 

}

+0

Da das Abfangen von Ausnahmen ein zeitraubender Prozess ist, sollte dies meine letzte Option sein. Aber wenn es keinen anderen Weg gibt, muss ich es so machen. Danke für deine Antwort! – Radinator

3

Da der Code für die Klasse Dns ist unter https://github.com/Microsoft/referencesource/blob/master/System/net/System/Net/DNS.cs verfügbar Sie nur den entsprechenden Teil von dort nutzen können. (Natürlich müssen Sie überprüfen, ob die MIT-Lizenz in Ihrem Projekt verwendet werden kann)

Die Implementierung ist in der Methode InternalGetHostByAddress, wo die Ausnahmen ausgelöst werden. Dort könnten Sie einfach einen Wert (bool, enum ...) zurückgeben, um Informationen zu liefern, wenn die Abfrage erfolgreich war.

+0

Das war das erste, was ich versuchte, nachdem ich die Frage gepostet hatte ... Schande über mich ... – Radinator

Verwandte Themen