Wygląda na to, że wszystkie sprawy, które powodowały duże opóźnienia, można było rozwiązać dużo szybciej, próbując wykonać bezpośrednie połączenie z gniazdem w ten sposób:
foreach (string svrName in args)
{
try
{
System.Net.Sockets.TcpClient tcp = new System.Net.Sockets.TcpClient(svrName, 1433);
if (tcp.Connected)
Console.WriteLine("Opened connection to {0}", svrName);
else
Console.WriteLine("{0} not connected", svrName);
tcp.Close();
}
catch (Exception ex)
{
Console.WriteLine("Error connecting to {0}: {1}", svrName, ex.Message);
}
}
Użyję tego kodu, aby sprawdzić, czy serwer odpowiada na porcie SQL Server i spróbuję otworzyć połączenie tylko wtedy, gdy tak. Myślałem (w oparciu o doświadczenie innych), że nawet na tym poziomie będzie 30 sekund opóźnienia, ale otrzymuję komunikat, że maszyna „aktywnie odmówiła połączenia” od razu.
Edytuj: A jeśli maszyna nie istnieje, od razu mi to mówi. Brak 30-sekundowych opóźnień, które mogę znaleźć.
Edytuj: Maszyny, które były w sieci, ale nie są wyłączone, nadal potrzebują 30 sekund na awarię. Maszyny chronione zaporą ogniową zawodzą jednak szybciej.
Edytuj: Oto zaktualizowany kod. Czuję, że czyściej jest zamknąć gniazdo niż przerwać wątek:
static void TestConn(string server)
{
try
{
using (System.Net.Sockets.TcpClient tcpSocket = new System.Net.Sockets.TcpClient())
{
IAsyncResult async = tcpSocket.BeginConnect(server, 1433, ConnectCallback, null);
DateTime startTime = DateTime.Now;
do
{
System.Threading.Thread.Sleep(500);
if (async.IsCompleted) break;
} while (DateTime.Now.Subtract(startTime).TotalSeconds < 5);
if (async.IsCompleted)
{
tcpSocket.EndConnect(async);
Console.WriteLine("Connection succeeded");
}
tcpSocket.Close();
if (!async.IsCompleted)
{
Console.WriteLine("Server did not respond");
return;
}
}
}
catch(System.Net.Sockets.SocketException ex)
{
Console.WriteLine(ex.Message);
}
}