检查.NET远程服务器的presence - 是我的方法正确吗? [英] Checking for presence of .NET remoting server - is my approach correct?

查看:177
本文介绍了检查.NET远程服务器的presence - 是我的方法正确吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是不可能在.NET远程调用设置连接超时。文档有时是指的TcpChannel 性能据称这样做,但<一个href="http://social.msdn.microsoft.com/Forums/en/netfxremoting/thread/22d06986-b0a3-42f8-a5bd-43e950302fdf"相对=nofollow>讨论的和最新的文档我发现表明这是不可能的。人们可以设置在远程调用本身超时,但不是在初始连接尝试。你坚持使用默认45秒超时。

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

这会导致一个问题,当远程服务器上消失。如果我试图做一个远程调用,我坚持对那些45秒。这不好。我要检查的远程服务器的presence。与侦测它 PingTimeout 是最简单的方法,但我要检查专为远程服务器上,而不是仅仅在机器往上冲。

一些试验后,我想出了这个办法:

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

这工作,但我不确定我用我的WaitHandle和插座。我也想保证线程安全WRT并发检查,我认为我所做的一切。我的code的下面。你看到的任何问题,我的做法?

 私有静态布尔IsChannelOpen(字符串IP,INT端口,INT超时)
{
    IPEndPoint端点=新IPEndPoint(IPAddress.Parse(IP),端口);
    客户端的Socket =新的Socket(endpoint.AddressFamily,
              SocketType.Stream,ProtocolType.Tcp);
    SocketTestData数据=新SocketTestData()
              {插座=客户端,ConnectDone =新的ManualResetEvent(假)};
    IAsyncResult的AR = client.BeginConnect
              (终点,新的AsyncCallback(TestConnectionCallback),数据);

    //等待连接成功从回调的信号,或超时
    data.ConnectDone.WaitOne(超时);
    client.Close();
    返回data.Connected;
}

私有静态无效TestConnectionCallback(IAsyncResult的AR)
{
    SocketTestData数据=(SocketTestData)ar.AsyncState;
    data.Connected = data.Socket.Connected;
    如果(data.Socket.Connected)
    {
        data.Socket.EndConnect(AR);
    }
    data.ConnectDone.Set(); //信号完成
}

公共类SocketTestData
{
    公共插槽插槽{获得;组; }
    公共ManualResetEvent的ConnectDone {获得;组; }
    公共BOOL连接{获得;组; }
}
 

解决方案

你的方法似乎不错,但会更倾向于包装在一个使用,以确保无资源泄漏插座code在 IsChannelOpen 功能,将其套在try / catch块也,仿佛连接失败,你会得到,如果发生了,你的$ C $套接字异常讨厌的惊喜Ç跳下成永远不会再看到树林里。

下面是我认为应该怎样做才能稳健,IFY的code:

 私有静态布尔IsChannelOpen(字符串ip地址,INT端口,INT超时)
    {
        IPEndPoint端点=新IPEndPoint(IPAddress.Parse(ip地址),端口);
        SocketTestData数据;
        尝试
        {
            使用(客户端的Socket =新的Socket(endpoint.AddressFamily,
                      SocketType.Stream,ProtocolType.Tcp))
            {

                数据=新SocketTestData(){插座=客户端,ConnectDone =新的ManualResetEvent(假)};
                IAsyncResult的AR = client.BeginConnect
                          (终点,新的AsyncCallback(TestConnectionCallback),数据);

                //等待连接成功从回调的信号,或超时
                data.ConnectDone.WaitOne(超时);
            }
        }
        赶上(System.Net.Sockets.SocketException sockEx)
        {
        }
        赶上(System.Exception的前)
        {
        }
        返回data.Connected;
    }

    私有静态无效TestConnectionCallback(IAsyncResult的AR)
    {
        SocketTestData数据=(SocketTestData)ar.AsyncState;
        data.Connected = data.Socket.Connected;
        data.Socket.EndConnect(AR);
        data.ConnectDone.Set(); //信号完成
    }

    公共类SocketTestData
    {
        公共插槽插槽{获得;组; }
        公共ManualResetEvent的ConnectDone {获得;组; }
        公共BOOL连接{获得;组; }
    }
 

It's not possible to set a connection timeout on a .NET remoting call. Documentation occasionally refers to TcpChannel properties that allegedly do this, but discussions and the most recent docs I've found indicate that this is not possible. One may set a timeout on the remoting call itself, but not on the initial connection attempt. You're stuck with the default 45-second timeout.

For various reasons I can't use WCF.

This causes a problem when the remoting server goes away. If I attempt to make a remoting call, I'm stuck for those 45 seconds. That's not good. I want to check for the presence of the remoting server. Pinging it with a PingTimeout is the simplest approach, but I want to check specifically for the remoting server, as opposed to just the machine being up.

After some experimentation, I've come up with this approach:

  1. Asynchronously begin a TCP socket connection to the remoting port.
  2. Wait for the connection to complete, or a timeout to expire (using a ManualResetEvent).
  3. If the connection async callback succeeded, return success. Otherwise, return failure.

This works, but I'm unsure about my use of my WaitHandle and socket. I'd also like to assure thread-safety WRT concurrent checks, which I think I've done. My code's below. Do you see any problems with my approach?

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

解决方案

Your approach seems fine, but would be more inclined to wrap the socket code in a using to ensure no resource leak in IsChannelOpen function, and wrap it around the try/catch block also, as if the connection failed you'll get a nasty surprise if a socket exception occurred and your code jumps off into the woods never to be seen again.

Here is what I think should be done to robust-ify the code:

    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远程服务器的presence - 是我的方法正确吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆