Verificando a presença do servidor remoting .NET - minha abordagem está correta?
Não é possível definir um tempo limite de conexão em uma chamada remota do .NET. Documentação ocasionalmente se refere aTcpChannel propriedades que supostamente fazem isso, masdiscussões e o mais recentedocs Eu encontrei indicam que isso não é possível. Pode-se definir um tempo limite na própria chamada de comunicação remota, mas não na tentativa de conexão inicial. Você está preso com o tempo limite padrão de 45 segundos.
Por vários motivos, não consigo usar o WCF.
Isso causa um problema quando o servidor remoto desaparece. Se eu tentar fazer uma chamada remota, fico preso por esses 45 segundos. Isso não é bom. Eu quero verificar a presença do servidor de remoting. Pingando com umPingTimeout
é a abordagem mais simples, mas quero verificar especificamente o servidor remoto, em oposição a apenas a máquina estar ativa.
Depois de algumas experiências, descobri essa abordagem:
Assincronamente, inicie uma conexão de soquete TCP à porta remota.Aguarde a conclusão da conexão ou um tempo limite para expirar (usando um ManualResetEvent).Se o retorno de chamada assíncrona de conexão tiver êxito, retorne o sucesso. Caso contrário, retorne a falha.Isso funciona, mas não tenho certeza sobre o uso do meuWaitHandle
e soquete. Também gostaria de garantir verificações simultâneas de WRT de thread-safety, o que eu acho que fiz. Meu código está abaixo. Você vê algum problema com a minha abordagem?
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; }
}