es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

El socket C# con KeepAlive habilitado no envía cuando todas las conexiones están rotas.

Tengo una aplicación que abre un socket de transmisión TCP de solo lectura. He configurado KeepAlive para asegurarme de que se envíe un mensaje cada segundo para comprobar si la conexión sigue funcionando. Wireshark muestra que los mensajes KeepAlive se envían y también son reconocidos por la otra computadora. Mi aplicación se ejecuta en Windows.

La máquina remota a la que abro el socket está en un adaptador LAN separado del resto de la red / internet.

Hay dos escenarios que parecen reaccionar de manera diferente, y me gustaría saber por qué.

  1. Estoy conectado a internet. TCP Keep-Alive funciona bien cada segundo. Desconecto el cable LAN de la máquina. El último TCP Keep-Alive no es reconocido y, por lo tanto, Socket.Connected es false, como se esperaba.
  2. No estoy conectado a internet. TCP Keep-Alive funciona bien cada segundo. Desconecto el cable LAN de la máquina. No se envió ningún paquete TCP Keep-Alive a la máquina remota en absoluto, por lo tanto, Socket.Connected sigue siendo true.

¿Me falta un concepto importante aquí sobre cuándo se envía un paquete TCP Keep-Alive por el socket? Por ejemplo, ¿no enviar si no tiene conexión de red en absoluto? Y si es así, ¿cómo puedo asegurarme de que el socket ya no está conectado?

_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_socket.SetupKeepAlive();
_socket.Blocking = false;
public static void SetupKeepAlive(this Socket socket, uint interval = 1000U)
{
    if (socket is null)
    {
        throw new ArgumentNullException(nameof(socket));
    }

    // Obtener el tamaño del uint para usarlo como soporte del arreglo de bytes
    var size = Marshal.SizeOf(0U);

    // Crear el arreglo de bytes
    var keepAlive = new byte[size * 3];

    // Empaquetar el arreglo de bytes:
    // Activar keep-alive
    Buffer.BlockCopy(BitConverter.GetBytes(1U), 0, keepAlive, 0, size);

    // Establecer el tiempo sin actividad antes de enviar un keep-alive
    Buffer.BlockCopy(BitConverter.GetBytes(interval), 0, keepAlive, size, size);

    // Establecer el intervalo de keep-alive
    Buffer.BlockCopy(BitConverter.GetBytes(interval), 0, keepAlive, size * 2, size);

    // Establecer la configuración de keep-alive en el Socket subyacente
    _ = socket.IOControl(IOControlCode.KeepAliveValues, keepAlive, null);
}
Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    En el segundo escenario en el que la máquina no está conectada a internet, el paquete TCP Keep-Alive no se envía porque no hay conexión en absoluto. El paquete Keep-Alive solo se envía si hay una conexión establecida, y en este caso, no hay conexión con la máquina remota debido a la falta de conectividad de red.

    Para asegurarse de que el socket no esté conectado en este escenario, puede establecer un tiempo de espera en el socket utilizando la propiedad Socket.ReceiveTimeout. Esta propiedad determina la cantidad de tiempo que el socket esperará para recibir datos antes de generar una excepción. Establecer esta propiedad en un valor razonable garantizará que el socket se cierre correctamente cuando no hay conectividad de red.

    _socket.ReceiveTimeout = 1000; // Establecer un tiempo de espera de 1 segundo para recibir datos
    

    Alternativamente, puede utilizar el método Socket.Poll para comprobar si el socket sigue conectado. Este método se puede utilizar para comprobar si el socket sigue conectado después de que haya pasado el período de tiempo de espera:

    if (!_socket.Poll(1000, SelectMode.SelectRead) || _socket.Available == 0)
    {
        // El socket ya no está conectado
    }
    

    Este código comprobará si el socket sigue conectado después de esperar 1 segundo (parámetro de tiempo de espera de Poll) y comprobar si hay datos entrantes (SelectMode.SelectRead). Si el socket ya no está conectado o no hay datos entrantes, se considera que el socket está desconectado.

Comments are closed.