我正在尝试制作一个可以扫描网络中的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);
}
}
}
}
}
这是Controling对象和Scanner类.扫描程序类处理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
}
}
其所有有关行主机名= Dns.GetHostEntry(ip).HostName
因此:通过Dns.GetHostEntry()解决HostEntry时,如何避免使用try / catch?如果没有已知主机,是否有只返回null的函数?
提前致谢!
解决方法:
据我所知,没有像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
}
}