Mic*_*tta 3 .net sockets remoting
无法在 .NET 远程调用上设置连接超时。文档偶尔会提到据称可以执行此操作的TcpChannel属性,但讨论和我发现的最新文档表明这是不可能的。人们可以对远程调用本身设置超时,但不能对初始连接尝试设置超时。您被默认的 45 秒超时所困扰。
由于各种原因我无法使用WCF。
当远程服务器消失时,这会导致问题。如果我尝试进行远程调用,我就会被困在这 45 秒内。这不好。我想检查远程服务器是否存在。使用 a 对其执行 ping 操作PingTimeout是最简单的方法,但我想专门检查远程服务器,而不是仅检查正在运行的计算机。
经过一些实验,我想出了这种方法:
这可行,但我不确定我对 myWaitHandle和套接字的使用。我还想确保线程安全 WRT 并发检查,我想我已经做到了。我的代码如下。您认为我的方法有什么问题吗?
private static bool IsChannelOpen(string ip, int port, int timeout)
{
IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(ip), port);
Socket client = new Socket(endpoint.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
SocketTestData data = new SocketTestData()
{ Socket = client, ConnectDone = new ManualResetEvent(false) };
IAsyncResult ar = client.BeginConnect
(endpoint, new AsyncCallback(TestConnectionCallback), data);
// wait for connection success as signaled from callback, or timeout
data.ConnectDone.WaitOne(timeout);
client.Close();
return data.Connected;
}
private static void TestConnectionCallback(IAsyncResult ar)
{
SocketTestData data = (SocketTestData)ar.AsyncState;
data.Connected = data.Socket.Connected;
if (data.Socket.Connected)
{
data.Socket.EndConnect(ar);
}
data.ConnectDone.Set(); // signal completion
}
public class SocketTestData
{
public Socket Socket { get; set; }
public ManualResetEvent ConnectDone { get; set; }
public bool Connected { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
您的方法似乎不错,但更倾向于将套接字代码包装在 using 中,以确保IsChannelOpen函数中没有资源泄漏,并将其包装在 try/catch 块周围,就好像连接失败一样,如果发生套接字异常,您的代码跳入树林,再也不会出现。
我认为应该采取以下措施来增强代码的鲁棒性:
private static bool IsChannelOpen(string ipAddress, int port, int timeout)
{
IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(ipAddress), port);
SocketTestData data;
try
{
using (Socket client = new Socket(endpoint.AddressFamily,
SocketType.Stream, ProtocolType.Tcp))
{
data = new SocketTestData() { Socket = client, ConnectDone = new ManualResetEvent(false) };
IAsyncResult ar = client.BeginConnect
(endpoint, new AsyncCallback(TestConnectionCallback), data);
// wait for connection success as signaled from callback, or timeout
data.ConnectDone.WaitOne(timeout);
}
}
catch (System.Net.Sockets.SocketException sockEx)
{
}
catch (System.Exception ex)
{
}
return data.Connected;
}
private static void TestConnectionCallback(IAsyncResult ar)
{
SocketTestData data = (SocketTestData)ar.AsyncState;
data.Connected = data.Socket.Connected;
data.Socket.EndConnect(ar);
data.ConnectDone.Set(); // Signal completion
}
public class SocketTestData
{
public Socket Socket { get; set; }
public ManualResetEvent ConnectDone { get; set; }
public bool Connected { get; set; }
}
Run Code Online (Sandbox Code Playgroud)