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:
- Asynchronously begin a TCP socket connection to the remoting port.
- Wait for the connection to complete, or a timeout to expire (using a ManualResetEvent).
- 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; }
}