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