Checking for .NET Remote Server - Is My Approach Right?

Unable to set connection timeout on remote .NET call. The documentation sometimes refers to the TcpChannel properties that supposedly do this, but the discussions and recent docs I found show that this is not possible. You can set a timeout on the most remote call, but not on an attempt to initial connect. You are stuck with a default 45 second timeout.

For various reasons, I cannot use WCF.

This causes a problem when the remote server leaves. If I try to make a remote call, I am stuck for these 45 seconds. This is not good. I want to check for a remote server. Kicking it with PingTimeoutis the easiest approach, but I want to specifically check the remote access server, not just on the machine.

After some experimentation, I came up with this approach:

  • Asynchronously starts a TCP socket connection to a remote port.
  • Wait for the connection to complete, or the timeout (using ManualResetEvent).
  • If the connection asynchronous callback succeeds, return success. Otherwise, return failure.

This works, but I'm not sure about my use of mine WaitHandleand socket. I would also like to provide parallel WRT security checks with threads, which I think I did. My code is 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; }
}
+3
source share
2 answers

Your approach seems fine, but it will be more likely to wrap the socket code in with to ensure that there are no resource leaks in the function IsChannelOpenand wrap it around the try / catch block, as if the connection failed, you will get an unpleasant surprise if a socket exception occurs, and your code jumps into a forest that will no longer be visible.

Here is what I have to do for reliable 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; }
    }
+4

, .NET -. -. - , "connectionTimeout", "timeout". , , . , 2000 , 4000 . :

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

Source: https://habr.com/ru/post/1725344/


All Articles