我目前正在开发SNMP打印机监控软件的自动发现功能。我需要一个帮助方法,它从多个线程执行,每个线程检查一个范围内的ip,以确定某个IP地址的设备是否响应端口9100,以确定它实际上是一个打印机,然后再发送一个对它的SNMP请求。
我最终得到了以下方法,但是我不知道这是否是正确的方法,并且如果按照惯例正确使用此上下文中的Close()方法(我可以看到Dispose(),Disconnect ()和Shutdown()方法也可用,所以使用哪些?)。此外,我需要设置超时值max。 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;
}
设置超时属性无效。
答案 0 :(得分:1)
这是检查计算机/打印机是否在特定端口上的某个IP上联机的正确方法。
您应该调用dispose方法来释放对象使用的内存。
Socket类实现了IDisposable,因此最好使用using
而不用担心调用dispose,因为using
为你做了。
using(Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
//...
}
Socket类具有ReceiveTimeout和SendTimeout属性。
答案 1 :(得分:1)
没有必要为此使用多线程。您正在占用最终将等待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
使用计时器,不是真的必要),但它易于编写,理解和使用,并且不会不必要地浪费线程。 / p>
电话会是这样的:
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。