2017-02-03 7 views
3

私はARP要求のネットワークをスキャンし、既存のネットワークデバイスをすべて一覧表示するアプリケーションを作成しようとしています。現在私はSharpPcapPacketDoNetを使用しています。ホスト名を解決する際の例外の防止

特定のIPに従ってホスト名を解決すると、「不明な」ホストを解決するときにSocketExceptionと表示されます。だから私はこれをtry/catchに入れました。私はこれが(例外を無視する)悪いスタイルだと思うので、私は別の解決策を探しています。ここで

はいくつかのコードです:これはスキャナを保持している制御対象であり、

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

イベントのために世話をする、パケットを受け入れ、キュー

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

にそれらを置くですオブジェクトとスキャナクラスの制御。スキャナクラスは、ARP要求を動作し、ラインhostname = Dns.GetHostEntry(ip).HostName

についてのすべてのホスト名

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

そのを解決しますので:私はDns.GetHostEntry経由HostEntryを解決するときのtry/catchを使用して回避することができますどのように()?既知のホストがない場合、ただnullを返す関数はありますか?

ありがとうございます!

答えて

1

私が知る限り、例外をスローしないTryGetHostName()のようなメソッドはありません。

私の意見では、あなたが期待している限り例外をキャッチするのは読みやすいです。だから、あなたが期待するものに例外をキャッチ制限する必要があります。

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 
} 

}クラスDnsためのコードとして

+0

例外のキャッチには時間がかかるため、これは私の最後の選択肢です。しかし、それ以外の方法がないとすれば、私はこのようにしなければなりません。あなたの答えをありがとう! – Radinator

3

は、あなたがそこにのみ関連部分から使用することができますhttps://github.com/Microsoft/referencesource/blob/master/System/net/System/Net/DNS.csで利用することができます。 (もちろん、プロジェクトでMITライセンスを使用できるかどうかを確認する必要があります)

実装方法はInternalGetHostByAddressで、例外がスローされます。そこでは、クエリが成功した場合に情報を提供するための値(bool、enum ...)を返すことができます。

+0

それは質問を投稿した後に私が試した最初のことでした...私には恥が... – Radinator

関連する問題