He estado peleando con un problema durante 3 días enteros No encuentro ninguna solución, por favor ayuda :)
Trabajo con Visual Studio 2010 y C# language.¿Cómo se prueba una conexión interrumpida de TCPClient después de conectarse?
Tengo un dispositivo que funciona como un servidor, que envía algunos datos en períodos muy irregulares (no es posible definir ningún tiempo de espera de lectura).
Escribí un cliente TCP para conectarme a ese servidor y leer datos. Funciona bien, sin embargo, cuando algo falla en la red y el servidor deja de estar disponible (por ejemplo, cuando desconecto el cable de red de mi computadora), la aplicación tarda unos 10 segundos en "notar" que no hay conexión con el servidor y lanzar una excepción. (No sé por qué exactamente 10 segundos? ¿Dónde está definido? ¿Puedo cambiarlo?)
Quiero reaccionar más rápido, digamos después de un segundo después de la conexión rota.
Google para la respuesta, sin embargo, no me proporciona ninguna solución de trabajo.
El código de prueba está debajo, intento hacerlo en 2 hilos: uno está leyendo datos, el segundo está buscando el estado de la conexión y debería alertarme cuando está roto. No está funcionando ni para TCPClient ni para la clase Socket. Intenté leer/escribir algunos datos con tcpClient.SendTimeout = 100;
y stream.WriteTimeout = 100;
, pero parece que no funciona.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
namespace TCPClient
{
class Program
{
static volatile bool _continue = true;
static TcpClient tcpClient;
static NetworkStream stream;
static void Main(string[] args)
{
try
{
//client thread - listen from server
Thread tcpListenThread = new Thread(TcpListenThread);
tcpListenThread.Start();
//connection checking thread
Thread keepAliveThread = new Thread(KeepAliveThread);
keepAliveThread.Start();
while (_continue)
{
if (Console.ReadLine() == "q")
{
_continue = false;
}
}
keepAliveThread.Join(2000);
if (keepAliveThread.IsAlive)
{
Console.WriteLine("Thread keepAlive has been aborted...");
keepAliveThread.Abort();
}
tcpListenThread.Join(2000);
if (tcpListenThread.IsAlive)
{
Console.WriteLine("Listen thread has been aborted...");
tcpListenThread.Abort();
}
}
catch (Exception ex)
{
Console.WriteLine("\n" + ex.Message);
}
Console.WriteLine("\nHit any key to quit...");
Console.Read();
}
private static void TcpListenThread()
{
string server = "172.20.30.40";
int port = 3000;
try
{
using (tcpClient = new TcpClient())
{
tcpClient.Connect(server, port);
if (tcpClient.Connected)
Console.WriteLine("Successfully connected to server");
using (stream = tcpClient.GetStream())
{
while (_continue)
{
Byte[] data = new Byte[1024];
Int32 bytes = stream.Read(data, 0, data.Length);
string responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}, responseData);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Listen thread exception! " + ex.Message);
}
}
private static void KeepAliveThread()
{
while (_continue)
{
if (tcpClient != null)
{
try
{
//...what to put here to check or throw exception when server is not available??...
}
catch (Exception ex)
{
Console.WriteLine("Disconnected...");
}
}
Thread.Sleep(1000); //test for connection every 1000ms
}
}
}
}
Editar:
@ respuesta Carsten: a pesar de que parece prometedor, esta solución no funciona ...
Hice la aplicación de prueba más simple para ello:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
namespace TCPClientTest
{
class Program
{
static void Main(string[] args)
{
try
{
string server = "172.20.30.40";
int port = 3000;
using (TcpClient tcpClient = new TcpClient())
{
tcpClient.Connect(server, port);
int i = 0;
while (true)
{
// This is how you can determine whether a socket is still connected.
bool blockingState = tcpClient.Client.Blocking;
try
{
byte[] tmp = new byte[1];
tcpClient.Client.Blocking = false;
tcpClient.Client.Send(tmp, 0, 0);
Console.WriteLine("Connected!");
}
catch (SocketException e)
{
// 10035 == WSAEWOULDBLOCK
if (e.NativeErrorCode.Equals(10035))
Console.WriteLine("Still Connected, but the Send would block");
else
{
Console.WriteLine("Disconnected: error code {0}!", e.NativeErrorCode);
}
}
finally
{
tcpClient.Client.Blocking = blockingState;
}
Console.WriteLine("Connected: {0} ({1})", tcpClient.Client.Connected, i++);
Thread.Sleep(1000);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Global exception: {0}", ex.Message);
}
}
}
}
Los resultados están siguiendo, muestra:
Connected!
Conectado: Verdadero
más mi número de pedido cada un segundo. Cuando desconecto el cable de red, toma 8 segundos comenzar a imprimir:
Desconectado: código de error 10054!
Conectado: Falso
por 8 segundos No estoy al tanto de que se haya perdido la conexión. Parece que hacer ping es la mejor opción aquí, pero probaré otras soluciones.
Posible duplicado: [¿Cómo puedo comprobar si un conector (TCP) está (des) conectado en C#?] (Http://stackoverflow.com/questions/515458/how-can-i- check-whether-a -tcp-socket-is-disconnected-in-c) – ladenedge
@ladenedge Posible duplicado ... excepto que tiene más código de ejemplo para ayudar a otras personas a aprender de una manera diferente.Sé que su comentario es antiguo, sin embargo, es frustrante cuando personas como usted hacen comentarios inútiles y desalentadores que no son productivos. – Euthyphro