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.

C# – Cómo saber cuántos bytes quedan en TcpClient después de realizar SslStream.Read

Estoy desarrollando una aplicación cliente-servidor, el servidor verificará cuando haya datos disponibles (TcpClient.Available > 0) para leer, pero cuando se ejecuta SslStream.Read, aunque sé cuántos bytes necesito leer, aún establece TcpClient.Available en 0 y deja los bytes ya leídos sin leer por mi código porque la condición (TcpClient.Available > 0) sería falsa, por lo que el servidor no hará nada con los bytes adicionales hasta que el cliente envíe más bytes, lo cual no es deseado, el servidor debe procesar todos los bytes enviados por el cliente lo antes posible.

Aquí hay un poco de código:

static void Main()
{
    TcpClient tcpClient = listener.AcceptTcpClient();
    SslStream s = new SslStream(tcpClient.GetStream(), false);
    // autenticar etc ...
    while (true)
    {
        if (tcpClient.Available > 0) // ahora esta condición es falsa hasta que
                                 // el cliente envíe más bytes
                                 // lo cual no es deseado
            work(tcpClient);
    }
}

static void work(TcpClient c)
{
    // el cliente envío 50 bytes
    byte[] data = new byte[10];
    s.Read(data, 0, 10); // Sé que no está garantizado leer 10 bytes
    // así que tengo un bucle while para leer hasta que reciba todos los bytes, esta línea es solo un ejemplo

    // hacer algo con los 10 bytes que leí, volver al bucle while
}

Mi “work” en realidad crea un nuevo hilo para hacer el trabajo y bloquea ese cliente hasta que se haya completado el trabajo, de manera que ese cliente no llamará a “work” hasta que se haya completado el trabajo.

Dado que sé cuántos bytes se necesitan para que se ejecute un “work”, solo leo esa cantidad de bytes y desbloqueo el cliente para que pueda “trabajar” nuevamente.

Y por supuesto, hay otros clientes que también necesitan trabajar, aquí solo muestro uno para demostrar el problema.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Parece que el problema radica en el hecho de que el método SslStream.Read establecerá la propiedad TcpClient.Available en 0 incluso si todavía hay bytes no leídos en el flujo. Esto plantea un problema para el servidor, ya que no sabrá que hay bytes adicionales para procesar y esperará más datos del cliente antes de actuar sobre ellos.

    Una posible solución a este problema es usar un búfer para almacenar los datos entrantes hasta que se hayan recibido todos los bytes requeridos. Puede crear una matriz de bytes del tamaño requerido y luego usar un bucle para llamar repetidamente al método SslStream.Read hasta que se hayan leído todos los bytes. Una vez que tenga todos los bytes, puede procesarlos según sea necesario.

    Aquí hay una versión actualizada del código que ilustra este enfoque:

    static void main()
    {
        TcpClient tcpClient = listener.AcceptTcpClient();
        SslStream sslStream = new SslStream(tcpClient.GetStream(), false);
        // autenticar, etc...
        while (true)
        {
            if (tcpClient.Available > 0)
            {
                // el cliente envió datos, leerlos en un búfer
                byte[] buffer = new byte[50];
                int bytesRead = 0;
                while (bytesRead < buffer.Length)
                {
                    bytesRead += sslStream.Read(buffer, bytesRead, buffer.Length - bytesRead);
                }
    
                // procesar los datos
                work(tcpClient, buffer);
            }
        }       
    }
    
    static void work(TcpClient c, byte[] data)
    {
        // hacer algo con los datos
    }
    

    En esta versión del código, leemos todos los bytes en un búfer antes de llamar al método work. Esto asegura que todos los datos se procesen tan pronto como estén disponibles, sin esperar datos adicionales del cliente.

Comments are closed.