代码之家  ›  专栏  ›  技术社区  ›  Michael Petrotta user3140870

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

  •  3
  • Michael Petrotta user3140870  · 技术社区  · 16 年前

    TcpChannel 据称是这样做的财产,但 discussions docs 我发现这是不可能的。可以在远程处理调用本身上设置超时,但不能在初始连接尝试上设置超时。您将无法使用默认的45秒超时。

    当远程处理服务器离开时,这会导致问题。如果我试图打一个远程电话,我会被困45秒。那不好。我想检查远程处理服务器是否存在。用锤子敲打它 PingTimeout 这是最简单的方法,但我想专门检查远程处理服务器,而不仅仅是启动机器。

    经过一些实验,我提出了以下方法:

    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; }
    }
    
    2 回复  |  直到 10 年前
        1
  •  4
  •   Peter Mortensen Pieter Jan Bonestroo    12 年前

    您的方法看起来不错,但更倾向于将套接字代码封装在 确保没有资源泄漏 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; }
        }
    
        2
  •  2
  •   Community Mohan Dere    9 年前

    我不敢相信.NET远程处理不支持超时。我在堆栈溢出问题中找到了一个提示 Remoting set timeout . 有人声称该属性是“connectionTimeout”,但根据我的测试,它是“timeout”属性。它正在工作,只是并没有达到您指定的确切时间。大致上,如果指定2000毫秒,它将在4000毫秒时超时。这是我的密码:

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