Я пытаюсь создать приложение, которое сканирует сеть для запросов 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
, если нет известного хоста?
Заранее благодарен!
так как отлавливание исключений является трудоемким процессом, это должен быть мой последний вариант. Но, если нет другого пути, мне кажется, я должен сделать это таким образом. Спасибо вам за ваш ответ! – Radinator