2010-04-06 19 views
5

Supongamos que tenemos un socket de internet simple, y enviará 10 megabytes (porque quiero ignorar problemas de memoria) de datos aleatorios. ¿Existe alguna diferencia en el rendimiento o un método de mejores prácticas que uno debería usar para recibir datos? Los datos finales de salida deben estar representados por un byte []. Sí, sé que escribir una cantidad arbitraria de datos en la memoria es mala, y si estuviera descargando un archivo grande, no lo haría así. Pero, por el bien de los argumentos, ignorémoslo y supongamos que se trata de una cantidad pequeña de datos. También me doy cuenta de que el cuello de botella aquí probablemente no sea la gestión de la memoria sino la recepción del socket. Solo quiero saber cuál sería el método más eficiente para recibir datos.C# métodos de rendimiento para recibir datos de un socket?

Algunas maneras poco fiables ocurre es:

  1. tener una lista y un tampón, después de que el buffer está lleno, agregarlo a la lista y al final list.ToArray() para obtener el byte []

  2. Escribe el búfer en una secuencia de memoria, después de su construcción completa un byte [] de la secuencia.Longitud y léelo todo en ella para obtener la salida de byte [].

¿Hay una forma más eficiente/mejor de hacer esto?

Respuesta

3

Simplemente escriba en MemoryStream y luego llame al ToArray - eso hace la tarea de construir una matriz de bytes del tamaño adecuado para usted. Eso es efectivamente lo que sería List<byte> de todos modos, pero usar un MemoryStream será mucho más simple.

+0

Sí, esta parece ser la respuesta más simple pero buena, ¡gracias! – Daniel

-1

Puede escribir en una secuencia de memoria, luego usar un lector de secuencias o algo así para obtener los datos. ¿Qué estás haciendo con los datos? Lo pregunto porque sería más eficiente desde el punto de vista de la memoria escribir los datos entrantes en un archivo o tabla de base de datos cuando se están recibiendo los datos en lugar de almacenar todo el contenido en la memoria.

+0

Probablemente lo convierta en una cadena – Daniel

0

¿Cuál es la codificación de sus datos? ¿es simple ASCII, o es algo más, como UTF-8/Unicode?

si es ASCII simple, podría asignar un StringBuilder() del tamaño requerido (obtener el tamaño del encabezado ContentLength de la respuesta) y seguir agregando sus datos al generador, después de convertirlo en una cadena usando Encoding.ASCII.

Si tiene Unicode/UTF8, entonces tiene un problema: no puede simplemente llamar a Encoding..GetString (buffer, 0, bytesRead) en los bytes leídos, porque bytesRead podría no constituir un fragmento de cadena lógico en esa codificación. Para este caso, deberá almacenar el cuerpo entero de la entidad en la memoria (o archivo), luego leer ese archivo y decodificarlo usando la codificación.

+0

¡Es ASCII y es una muy buena idea! ¿Por qué otras codificaciones necesitarán la cantidad completa para poder convertirse correctamente? – Daniel

+0

Oh, porque si están usando 2 bytes por carácter, si recibe 7bytes e intenta convertirlo, se producirán problemas. Pero podrías obtener el 0-6 y amortiguar el 1 ¿no? Poco más trabajo pero menos presión de memoria – Daniel

1

Bueno, la respuesta de Jon Skeet es genial (como siempre), pero no hay código, así que aquí está mi interpretación. (Funcionó bien para mí.)

using (var mem = new MemoryStream()) 
{ 
    using (var tcp = new TcpClient()) 
    { 
     tcp.Connect(new IPEndPoint(IPAddress.Parse("192.0.0.192"), 8880)); 
     tcp.GetStream().CopyTo(mem); 
    } 
    var bytes = mem.ToArray(); 
} 

(¿Por qué no combinar los dos using s? Bueno, si desea depurar, es posible que desee liberar la conexión TCP antes de tomar su tiempo buscando en los bytes recibidos.)

Este código recibirá múltiples paquetes y agregará sus datos, FYI. Por lo tanto, es una buena forma de recibir simplemente todos los datos de tcp enviados durante una conexión.

Cuestiones relacionadas