检查IP地址和端口是否有响应
本文关键字:是否 响应 IP 地址 检查 | 更新日期: 2023-09-27 18:00:36
我目前正在为SNMP打印机监视器软件开发一个自动发现功能。我需要一个助手方法,它由几个线程执行,每个线程检查一个范围内的ip,以确定某个ip地址的设备是否响应端口9100,并在向其发送SNMP请求之前确定它实际上是一台打印机
我最终得到了以下方法,但我不知道这是否是正确的方法,也不知道按照惯例,在这种情况下Close()方法的使用是否正确(我可以看到Dispose()、Disconnect()和Shutdown()方法也可用,那么该用哪种方法呢?)。此外,我需要设置一个最长5秒的超时值,这样线程在显示结果之前不会停留太久。到目前为止我的代码:
private bool GetTCPPrinterResponse(IPAddress _ip)
{
int port = 9100;
bool isResponsive = false;
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
s.Connect(_ip, port);
isResponsive = true;
}
catch (SocketException)
{
isResponsive = false;
}
finally
{
s.Close();
}
return isResponsive;
}
方法编辑后:
private bool GetTCPPrinterResponse(IPAddress _ip)
{
int port = 9100;
bool isResponsive = false;
using (Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
s.ReceiveTimeout = 3000;
s.SendTimeout = 3000;
try
{
s.Connect(_ip, port);
isResponsive = true;
}
catch (SocketException)
{
isResponsive = false;
}
}
return isResponsive;
}
设置Timeout属性无效。
这是检查计算机/打印机是否在某个端口的某个IP上联机的正确方法。您应该调用dispose方法来释放对象正在使用的内存。Socket类实现IDisposable,因此最好使用using
,而不用担心调用dispose,因为using
会为您执行此操作。
using(Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
//...
}
套接字类具有属性ReceiveTimeout和SendTimeout。
没有必要为此使用多线程。您正在占用线程,这些线程最终将等待I/O操作完成。相反,为什么不使用异步I/O呢?
public async Task<Tuple<IPAddress, bool>> GetResponse(IPAddress address)
{
using (var client = new TcpClient(AddressFamily.InterNetwork))
{
var connectTask = client.ConnectAsync(address, 80);
await Task.WhenAny(connectTask, Task.Delay(5000));
if (connectTask.IsCompleted)
return Tuple.Create(address, true);
else
return Tuple.Create(address, false);
}
}
这一点可以进一步改进——超时机制有点浪费(Task.Delay
使用定时器,不是真正必要的),但它很容易编写、理解和使用,而且不会不必要地浪费线程。
然后电话会是这样的:
Task<Tuple<IPAddress, bool>>[] tasks =
new []
{
GetResponse(Dns.GetHostAddresses("www.google.com").First()),
GetResponse(Dns.GetHostAddresses("www.microsoft.com").First()),
GetResponse(Dns.GetHostAddresses("www.yahoo.com").First()),
GetResponse(Dns.GetHostAddresses("www.altavista.com").First()),
};
Task.WhenAll(tasks).Wait();
foreach (var t in tasks)
t.Result.Dump(); // t.Result has the IP address and status
这将等待所有设备做出响应(或超时)。当然,没有什么可以阻止你以一种更具交互性的方式来做这件事——你可以在数据返回时轻松地用数据更新UI。