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

时间:2009-12-10 23:20:02

标签: .net sockets remoting

无法在.NET远程处理调用上设置连接超时。文档偶尔会引用据称执行此操作的TcpChannel属性,但discussions和我发现的最新docs表示这是不可能的。可以在远程调用本身设置超时,但不在初始连接尝试上设置超时。你被困在默认的45秒超时。

由于各种原因,我无法使用WCF。

当远程处理服务器消失时,这会导致问题。如果我试图拨打一个遥控电话,我会坚持45秒。这不好。我想检查远程服务器的存在。使用PingTimeout对其进行ping操作是最简单的方法,但我想专门检查远程处理服务器,而不仅仅是机器正在运行。

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

  1. 异步启动TCP套接字 连接到远程端口。
  2. 等待连接完成, 或者超时到期(使用 ManualResetEvent的)。
  3. 如果连接 异步回调成功,返回 成功。否则,返回失败。
  4. 这有效,但我不确定我使用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; }
    }
    

2 个答案:

答案 0 :(得分:4)

您的方法似乎很好,但更倾向于将套接字代码包装在中使用以确保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; }
    }

答案 1 :(得分:2)

我无法相信.NET远程处理不支持超时。我在Stack Overflow问题 Remoting set timeout 中找到了一个提示。在那里,有人声称该属性是“connectionTimeout”,但根据我的测试,它是“超时”属性。它正在工作,只是没有确切的指定时间。粗略地说,如果你指定2000毫秒,它会超过4000毫秒。这是我的代码:

   IDictionary dic = new Hashtable();
   dic["timeout"] = 2000;
   ChannelServices.RegisterChannel(new HttpChannel(dic, null, null), false);
   ...