我正在开发一个托管浏览器控件的应用程序。客户端(在浏览器中,使用本地主机地址)通过websockets与服务器通信,服务器处理Http请求。
用户可以为Http和Ws定义端口,但是(因为可以打开应用程序的几个实例)我需要检测,如果它们可用 - 如果没有,我通知用户将使用备用端口
使用HttpListener
验证是否阻止了预期的Http端口,但是(由于我不明白的原因),侦听器显然可以使用另一个应用程序已经使用的端口进行websocket连接。
所以我最终得到了以下代码,似乎可以完成这项工作。我用它来首先测试一个指定的端口,如果失败了,我会遍历一系列端口号并尝试直到该方法返回True
。
private static bool testPort(int port)
{
bool result = false;
System.Net.IPEndPoint endpoint = new System.Net.IPEndPoint(System.Net.IPAddress.Loopback, port);
using (System.Net.Sockets.Socket s = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP)) {
try {
Console.WriteLine("Testing port {0}", port);
s.Connect(endpoint);
s.Bind(endpoint);
result = true;
} catch (SocketException ex) {
switch (ex.SocketErrorCode) {
case SocketError.InvalidArgument:
//This error is apparently thrown when a port is occupied.
result = false;
break;
case SocketError.ConnectionRefused:
//NOTE: This error is apparently thrown when a port is not occupied (but the connection fails, because the socket cannot connect since the port is not being used?).
result = true;
break;
default:
result = false;
break;
}
} catch (Exception ex) {
result = false;
}
}
return result;
}
但我不确定,如果它可能只是一个“幸运的巧合”。就像我提到的那样,它可以测试它,但它有意义吗?而且:它可靠吗?
答案 0 :(得分:0)
代码受竞争条件限制。连接调用可能会失败,因为端口未被使用,但是另一个程序可能会在函数返回之前获取该端口。
测试一堆端口也可能导致明显的延迟。例如,防火墙可以配置为丢弃数据包而不是发送连接拒绝响应。在这种情况下,连接调用将阻塞,直到达到超时。
作为旁注,Bind
需要在Connect
工作之前调用,但在这种情况下,应删除Bind
调用。您无法将连接套接字绑定到您尝试连接的同一端点。