TcpClient.Connect dice "Un intento de conexión falló porque la parte conectada..."
Frecuentes
Visto 20,056 veces
2
Tengo una aplicación Visual Studio 2008 C# .NET 3.5 ejecutándose en Windows XP SP3 x86. En mi aplicación, tengo un controlador de eventos. OnSendTask
que puede ser llamado por múltiples subprocesos simultáneamente. Abre una conexión TCP a un host remoto y envía/recibe datos.
Por ejemplo:
/// <summary>
/// prevent us from exceeding the maximum number of half-open TCP
/// connections in Windows XP.
/// </summary>
private System.Threading.Semaphore tcp_connection_lock_ =
new System.Threading.Semaphore(10, 10);
public event EventHandler<SendTaskEventArgs> SendTask;
private void OnSendTask(object sender, SendTaskEventArgs args)
{
try
{
tcp_connection_lock_.WaitOne();
using (TcpClient recipient = new TcpClient())
{
// error here!
recipient.Connect(args.IPAddress, args.Port);
using (NetworkStream stream = recipient.GetStream())
{
// read/write data
}
}
catch
{
// write exceptions to the logfile
}
finally
{
tcp_connection_lock_.Release();
}
}
void SendTasks(int tasks_to_send)
{
using (ManualResetEvent done_event = new ManualResetEvent(false))
{
int countdown = tasks_to_send;
for (int i = 0; i < tasks_to_send; ++i)
{
ThreadPool.QueueUserWorkItem((o) =>
{
SendTaskEventArgs args = new SendTaskEventArgs(/*...*/);
EventHandler<SendTaskEventArgs> evt = SendTask;
if (evt != null)
evt(this, e);
if (Interlocked.Decrement(ref countdown) == 0)
done_event.Set();
}, i);
}
done_event.WaitOne();
}
}
Desafortunadamente, ocasionalmente veo este error:
System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 192.168.0.16:59596
at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
Algunos puntos de información:
- Si envío una tarea a 40 controles remotos, veré esta respuesta de alrededor de 6.
- Un seguimiento de Wireshark no muestra ningún intento de iniciar una conexión TCP desde la PC al control remoto.
- Puedo hacer ping al control remoto desde la PC y obtener buenas respuestas consistentes.
- Los controles remotos están todos en el mismo conmutador y subred que la PC que ejecuta esta aplicación. No hay redes sofisticadas en el camino.
¿Alguien puede sugerir qué puede estar causando este error o cómo puedo solucionarlo?
Muchas Gracias
1 Respuestas
3
No estoy seguro de todos los detalles detrás de las conexiones TCP semiabiertas máximas, pero creo que NO es específico de las conexiones de la aplicación, sino de todo el sistema. ¿Está seguro de que cuando ocurre este error no hay otras aplicaciones en el sistema que estén creando conexiones TCP?
Configuraría un reintento cada vez que ocurra un error. Algo como:
private const int MaxRetries = 10;
private void OnSendTask(object sender, SendTaskEventArgs args)
{
bool retry = false;
try
{
tcp_connection_lock_.WaitOne();
using (TcpClient recipient = new TcpClient())
{
// error here!
recipient.Connect(args.IPAddress, args.Port);
using (NetworkStream stream = recipient.GetStream())
{
// read/write data
}
}
}
catch (SocketException ex)
{
if(args.RetryCount < MaxRetries)
{
retry = true;
args.RetryCount++;
}
else
{
// write exceptions to the logfile
}
}
finally
{
tcp_connection_lock_.Release();
}
if(retry)
{
Thread.Sleep(1);
OnSendTask(sender, args);
}
}
contestado el 22 de mayo de 12 a las 22:05
Hice un poco más de análisis y resultó que el problema era que los controles remotos no siempre respondían a la solicitud ARP enviada antes que TCP SYN. (¿pila de TCP con errores?) Su solución soluciona el problema de manera efectiva porque ahora estamos enviando más solicitudes ARP, por lo que obtiene el punto de respuesta. :) - PaulH
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c# .net-3.5 tcpclient or haz tu propia pregunta.
Si envía una tarea a 1 remoto, ¿siempre tiene éxito? El mensaje de error hace que parezca que la ubicación remota está causando el problema. - C.Evenhuis
Nunca lo he visto fallar al enviar a 1 control remoto. Estoy de acuerdo con la forma en que suena el mensaje de error, pero el punto 2 sugiere que la PC ni siquiera está intentando establecer la conexión. - PaulH
Es posible que deba proporcionar más código. ¿Cómo se llama OnSendTask? ¿Dónde llamas a tcp_connection_lock_.Release()? - Eric Dahlvang
@EricDahlvang - Ups. ver actualización. OnSendTask se llama a través de un delegado de eventos que puede ser invocado por muchos subprocesos simultáneamente. Si 40 controles remotos reciben la tarea, 40 subprocesos simultáneos pueden alcanzar ese evento. Pero solo 10 pueden golpear el
TcpClient.Connect
llamada debido al semáforo. - PaulH¿Sigue recibiendo este error si ejecuta la aplicación en una máquina que no sea Windows XP SP3 x86? - Eric Dahlvang