socket receive net ejemplos async .net sockets

.net - receive - sockets c# ejemplos



¿Cuál es un buen tamaño de buffer para la programación de socket? (4)

8192 sería ideal. Si tiene datos que exceden este tamaño, sería mejor que envíe los datos en paquetes de longitud constante.

El tamaño de los datos que envía el servidor se puede verificar utilizando la función recv en WINSOCK, que tiene un parámetro que proporciona la longitud del búfer.

Estamos usando .Net y sockets. El servidor está utilizando el método Socket.Sender (bytes []) por lo que simplemente envía toda la carga útil. Por otro lado, somos clientes que consumen los datos. Socket.Receive (buffer []). En todos los ejemplos de Microsoft (y otros), parecen quedarse con un tamaño de búfer de 8192. Hemos utilizado este tamaño, pero de vez en cuando estamos enviando datos a los clientes que exceden este tamaño de búfer.

¿Hay alguna forma de determinar cuántos datos nos envió el método enviado por el servidor? ¿Cuál es el mejor tamaño de buffer?


Desafortunadamente, la respuesta de Jon Skeet deja una gran parte de la imagen: el tamaño del búfer de envío y el producto de retardo de ancho de banda de la tubería en la que está escribiendo.

Si está tratando de enviar datos a través de una tubería grande usando un solo socket, y desea que TCP llene esa tubería, necesita usar un tamaño de búfer de envío que sea equivalente al producto de ancho de banda de la tubería. De lo contrario, TCP no llenará la tubería porque no dejará suficientes ''bytes en vuelo'' en todo momento.

Considere una conexión que tiene una velocidad de 1 gigabit y tiene una latencia de un solo sentido de 10 milisegundos, en promedio. El tiempo de ida y vuelta (es decir, la cantidad de tiempo que transcurre entre el envío de un paquete por el socket y el tiempo que recibe el ack para ese paquete y, por lo tanto, sabe enviar más datos) suele ser el doble de la latencia.

Entonces, si tiene una conexión de 1 gigabit y un RTT de 20 milisegundos, entonces esa tubería tiene 1 gigabit / seg * 20 milisegundos == 2.5 megabytes de datos en vuelo en todo momento si se está utilizando por completo.

Si su búfer de envío TCP está a menos de 2.5 megabytes, entonces ese socket nunca utilizará completamente el conducto: nunca obtendrá un gigabit / seg de rendimiento de su socket.

Si su aplicación usa muchos sockets, entonces el tamaño agregado de todos los buffers de envío TCP debe ser de 2.5 MB para poder utilizar completamente esta tubería hipotética de 1 gigabit / 20 ms RTT. Por ejemplo, si usa búferes de 8192 bytes, necesita 306 zócalos TCP simultáneos para llenar esa tubería.


Incluso si está enviando más datos que eso, es posible que no esté disponible en una llamada para Recibir.

No puede determinar la cantidad de datos que ha enviado el servidor: es una secuencia de datos y solo está leyendo fragmentos a la vez. Puede leer parte de lo que el servidor envió en una llamada de envío, o puede leer los datos de dos llamadas de envío en una llamada de recepción. 8K es un tamaño de búfer razonable, no tan grande que perderá mucha memoria, y no tan pequeño que tendrá que usar muchas llamadas de recepción desperdiciadas. 4K o 16K posiblemente también estarían bien ... Yo personalmente no comenzaría a superar los 16K para los almacenamientos intermedios de la red. Sospecho que rara vez los llenarías.

Puede experimentar intentando usar un búfer muy grande y registrar cuántos bytes se recibieron en cada llamada, eso le daría una idea de cuánto está disponible en general, pero realmente no mostraría el efecto de usar un búfer más pequeño. ¿Qué preocupaciones tienes sobre el uso de un buffer 8K? Si se trata de rendimiento, ¿tiene alguna evidencia de que este aspecto de su código es un cuello de botella de rendimiento?


Depende de tu protocolo. Si espera mensajes de más de 8192 bytes, entonces debe aumentar el tamaño de su búfer según corresponda. Pero tenga en cuenta que este tamaño de buffer es solo para una llamada a Receive . Si realmente quiere / necesita hacerlo, puede Receive varias veces la Receive y copiar los datos recibidos en una estructura de datos o memoria intermedia arbitrariamente grande.

También tenga en cuenta que es una buena práctica llamar a Receive repetidamente hasta que haya verificado que ha leído todos los datos de un mensaje dado; incluso si un solo mensaje es menor que su tamaño de búfer, aún así puede que no sea recuperado por una única llamada de Receive .