2017-02-03 13 views
3

Я пытаюсь создать приложение, которое сканирует сеть для запросов ARP и перечисляет все существующие сетевые устройства. В настоящее время я использую SharpPcap и PacketDoNet.Предотвращение исключения при разрешении имени хоста

При разрешении имени хоста в соответствии с данным 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 и разрешает имена хостов

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

все о линии hostname = Dns.GetHostEntry(ip).HostName

Итак: Как я могу избежать использования TRY/поймать при разрешении HostEntry через Dns.GetHostEntry()? Есть функция, которая возвращает только 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 
} 

}

+0

так как отлавливание исключений является трудоемким процессом, это должен быть мой последний вариант. Но, если нет другого пути, мне кажется, я должен сделать это таким образом. Спасибо вам за ваш ответ! – Radinator

3

Как код для класса Dns доступно в соответствии с https://github.com/Microsoft/referencesource/blob/master/System/net/System/Net/DNS.cs вы можете использовать с там только соответствующей части. (Конечно, вы должны проверить, может ли лицензия MIT использоваться в вашем проекте)

Реализация в методе InternalGetHostByAddress, где выбрасываются исключения. Там вы можете просто вернуть значение (bool, enum ...), чтобы предоставить информацию, если запрос был успешным.

+0

Это было первое, что я пробовал после публикации вопроса ... позор мне ... – Radinator

 Смежные вопросы

  • Нет связанных вопросов^_^