Obtenga la longitud de los datos disponibles en NetworkStream

Me gustaría poder obtener la longitud de los datos disponibles de un flujo de red TCP en C # para establecer el tamaño del búfer antes de leer el flujo de red. Hay una propiedad NetworkStream.Length pero aún no está implementada, y no quiero asignar un tamaño enorme para el búfer ya que ocuparía demasiado espacio. La única forma en que lo pensé fue preceder a la transferencia de datos con otra indicando el tamaño, pero esto parece un poco desordenado. ¿Cuál sería la mejor manera para mí de hacer esto?

Cuando accede a Stream s , generalmente lee y escribe datos en fragmentos pequeños (por ejemplo, un kilobyte o algo así), o usa un método como CopyTo que lo hace por usted.

Este es un ejemplo que utiliza CopyTo para copiar el contenido de un flujo en otro flujo y devolverlo como un byte[] desde un método, utilizando un búfer de tamaño automático.

 using (MemoryStream ms = new MemoryStream()) { networkStream.CopyTo(ms); return ms.ToArray(); } 

Este es un código que lee los datos de la misma manera, pero más manualmente, lo que podría ser mejor para usted trabajar, dependiendo de lo que esté haciendo con los datos:

 byte[] buffer = new byte[2048]; // read in chunks of 2KB int bytesRead; while((bytesRead = networkStream.Read(buffer, 0, buffer.Length)) > 0) { //do something with data in buffer, up to the size indicated by bytesRead } 

(la base de estos fragmentos de código provino de la forma más eficiente de leer datos de un flujo )

La cuestión es que no se puede estar seguro de que todos los datos hayan sido leídos por el zócalo. Puede haber más datos en cualquier momento. Este es un bash incluso si de alguna manera sabe cuántos datos puede esperar, digamos si tiene un encabezado de paquete que contiene la longitud. El paquete completo podría no haber sido recibido todavía.

Si está leyendo datos arbitrarios (como quizás un archivo), debe tener un búfer de tamaño razonable (como 1k-10k o lo que sea que sea óptimo para su escenario) y luego escribir los datos en un archivo como se lee en el archivo stream.

 var buffer = byte[1000]; var readBytes = 0; using(var netstream = GetTheStreamSomhow()){ using(var fileStream = (GetFileStreamSomeHow())){ while(netstream.Socket.Connected) //determine if there is more data, here we read until the socket is closed { readBytes = netstream.Read(buffer,0,buffer.Length); fileStrem.Write(buffer,0,buffer.Length); } } } 

O simplemente use CopyTo como lo sugirió Tim 🙂 Simplemente asegúrese de que todos los datos hayan sido leídos, incluidos los datos que aún no han llegado a la red.

No hay una longitud inherente de un flujo de red. Tendrá que enviar la longitud de los datos a seguir desde el otro extremo o leer todos los datos entrantes en una secuencia diferente donde puede acceder a la información de longitud.

Podría enviar primero la longitud de los datos entrantes. Por ejemplo: tiene data = byte[16] que desea enviar. Entonces, al principio envía el 16 y define en el servidor, que esta longitud es siempre 2 (porque 16 tiene dos caracteres). Ahora usted sabe que la forma de incomingLength = 16 . Puede esperar ahora para los datos de la longitud incomingLength Longitud.