.net - 检查 .NET 远程服务器是否存在 - 我的方法是否正确?

标签 .net sockets remoting

无法在 .NET 远程调用上设置连接超时。文档偶尔会引用 TcpChannel据称这样做的属性,但是discussions和最近的 docs我发现表明这是不可能的。可以在远程调用本身上设置超时,但不能在初始连接尝试上设置。您受困于默认的 45 秒超时。

由于各种原因我不能使用 WCF。

当远程服务器消失时,这会导致问题。如果我尝试进行远程调用,我会被卡住那 45 秒。这不好。我想检查远程服务器是否存在。使用 PingTimeout 对其执行 Ping 操作是最简单的方法,但我想专门检查远程服务器,而不是仅仅检查正在运行的机器。

经过一些实验,我想出了这个方法:

  1. 异步开始一个 TCP 套接字 连接到远程端口。
  2. 等待连接完成, 或超时到期(使用 手动重置事件)。
  3. 如果连接 异步回调成功,返回 成功。否则返回失败。

这行得通,但我不确定我对 WaitHandle 和套接字的使用情况。我还想确保线程安全的 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; }
}

最佳答案

您的方法似乎不错,但更倾向于将套接字代码包装在 using 中以确保 IsChannelOpen 函数中没有资源泄漏,并将其包装在 try 中/catch block ,就好像连接失败一样,如果发生套接字异常并且您的代码跳入树林再也不会出现,您会感到非常惊讶。

以下是我认为应该对代码进行鲁棒化的做法:

    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; }
    }

关于.net - 检查 .NET 远程服务器是否存在 - 我的方法是否正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1884804/

相关文章:

c# - 将 Firefox 嵌入到 .NET 控件中

c# - NHibernate 模式更新

Python:将数据从扭曲的套接字读取到 SWIG-ed 结构中

PowerShell 远程处理给出 "Access is Denied"错误

java - Spring HttpInvoker : how to replace serviceUrl at runtime?

.net - 为什么 Microsoft .NET Framework Client Profile 是 256 MB?

c# - 将非托管和托管 dll 合并为 DotNet 中的单个 dll

Java tcp套接字转换为udp

android - 添加权限后应用程序崩溃?

apache-flex - [RemoteClass] 在 Flex Actionscript 中如何工作 我可以将它用于自定义数据绑定(bind)吗?