2011-07-13 8 views
9

Basado en el consejo de @ Len-Holgate in this question, solicito de manera asíncrona lecturas de 0 bytes, y en la devolución de llamada, acepto bytes los bytes disponibles con lecturas sincrónicas, ya que sé que los datos están disponibles y no se bloquearán. Esto parece tan eficiente y maravilloso.SslStream equivalente de TcpClient.Disponible?

Pero luego agrego la opción para SslStream, y el enfoque se desmorona. La lectura de cero bytes está bien, pero el SslStream descifra los bytes, dejando un recuento de bytes cero en el búfer del TcpClient (apropiadamente), y no puedo determinar cuántos bytes hay ahora en el SslStream disponible para leer.

¿Hay un simple truco en esto?


Algunos código, sólo para el contexto:

sslStream.BeginRead(this.zeroByteBuffer, 0, 0, DataAvailable, this); 

Y después de la EndRead() (que devuelve correctamente 0), DataAvailable contiene:

// by now this is 0, because sslStream has already consumed the bytes 
available = myTcpClient.Available; 

if (0 < available) // Never occurs 
{ 
    // this part can be distractingly complicated, but 
    // it's based on the available byte count 
    sslStream.Read(...); 
} 

Y debido al protocolo , Necesito evaluar byte por byte y descodificar el byte de ancho de bytes variable y todo eso. ¡No quiero tener que leer byte por byte de forma asíncrona!

+3

He creado muchas aplicaciones basadas en Socket, con o sin SSL, síncronas o asíncronas. Pero nunca me he encontrado con una situación en la que necesite saber la cantidad de bytes disponibles. Iría tan lejos y llamaría a una aplicación que depende de ella rota. ¿Puedes explicar por qué tu código necesita esto? ¿Por qué no simplemente solicita byteBuffer.Length muchos bytes? – dtb

+1

Porque no sé cuántos bytes necesitaré recibir antes, en este caso, un carácter de nueva línea. Si solicito 1024 bytes, la devolución de llamada no regresará hasta que estén disponibles 1024 bytes (o se llegue al final de la secuencia debido a que el socket está cerrado). A menos que me equivoque sobre esto? –

+2

Tanto Read como BeginRead devuelven solo lo que está disponible, a menos que no haya nada disponible, en cuyo caso esperan hasta que esté disponible al menos un byte o se cierre la secuencia. Por ejemplo, si solicita 1024 bytes, devolverán entre 1 y 1024 bytes, pero no esperarán hasta que se hayan recibido exactamente 1024 bytes. – dtb

Respuesta

1

Si he entendido bien, los mensajes están delimitados por un cierto carácter, y ya se están utilizando una StringBuilder para cubrir el caso cuando un mensaje se fragmenta en múltiples piezas.

Podría considerar ignorar el delimitador al leer datos, agregarle datos cuando estén disponibles, y luego inspeccionar el StringBuilder local para el carácter delimitador. Cuando se encuentra, puede extraer un solo mensaje usando sb.ToString(0, delimiterIndex) y sb.Remove(0, delimiterIndex) hasta que no queden delimitadores.

Esto también cubriría el caso cuando se reciben dos mensajes simultáneamente.