2017-02-03 8 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을 해석 할 때 시도/캐치를 사용하지 어떻게()? 알려진 호스트가없는 경우에만 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

관련 문제