2012-02-08 12 views
15

En Java cuando se usa DatagramPacket supongamos que tiene un almacenamiento intermedio byte[1024*1024]. Si acaba de pasar eso para el DatagramPacket al enviar/recibir una llamada de recepción de Java para el bloque de DatagramPacket hasta que haya leído todo el megabyte?Java DatagramPacket (UDP) Tamaño máximo de búfer de envío/recv

Pregunto si Java lo dividirá o simplemente tratará de enviar todo lo que se descarta.

Normalmente el límite de tamaño es de alrededor de 64KB para un paquete UDP, pero me pregunto porque la API de Java permite matrices de bytes si ese es un límite y se corta o se divide y se vuelve a ensamblar para usted.

Si se elimina, ¿qué llamada de API me diría la carga máxima de datos que puedo usar en la llamada Java? He oído que IPv6 también tiene frames jumbo, pero ¿admite DatagramPacket (o DatagramSocket) dado que UDP define la especificación del encabezado?

Respuesta

23

DatagramPacket es simplemente un contenedor en un socket basado en UDP, por lo que se aplican las reglas UDP habituales.

64 kilobytes es el tamaño máximo teórico de un datagrama IP completo, pero solo se garantiza que se enrutarán 576 bytes. En cualquier ruta de red determinada, el enlace con la unidad de transmisión máxima más pequeña determinará el límite real. (1500 bytes, menos encabezados es el máximo común, pero es imposible predecir cuántos encabezados habrá, por lo que es más seguro limitar los mensajes a alrededor de 1400 bytes).

Si supera el límite de MTU, IPv4 automáticamente divide el datagrama en fragmentos y vuelve a montarlos al final, pero solo hasta 64 kilobytes y solo si todos los fragmentos pasan. Si se pierde algún fragmento, o si algún dispositivo decide que no le gustan los fragmentos, entonces se pierde todo el paquete.

Como se indicó anteriormente, es imposible saber de antemano cuál será la MTU de la ruta. Existen varios algoritmos para experimentar, pero muchos dispositivos no implementan (o ignoran deliberadamente) los estándares necesarios, por lo que todo se reduce a prueba y error. O puede adivinar 1400 bytes por mensaje.

En cuanto a los errores, si intenta enviar más bytes de los que el sistema operativo está configurado para permitir, debería obtener un error EMSGSIZE o su equivalente. Si envía menos de eso pero más de lo que permite la red, el paquete simplemente desaparecerá.

+1

En realidad, la MTU mínima garantizada para IPv4 en toda la red es de solo 68 Byte: 576 es el mínimo que los hosts deben manejar. De cualquier manera, una MTU tan pequeña sería realmente inusual. – lxgr

+0

¿Eso significa que si tiene un tamaño de paquete superior a 64 KB, usaría un protocolo diferente? –

+0

@PhaniRahul: Diría que significa "gracias a Dios que el protocolo maneja la segmentación de forma transparente y convierte mis datos en tantos paquetes como sean necesarios". Dudo si algún protocolo práctico en uso le dará tamaños de paquete más grandes. :) –

-1

@ Mihai Danila. Como no pude agregar un comentario a la respuesta anterior, es por eso que escribo en la sección de respuesta.

En la continuación de su respuesta en el tamaño de MTU, en mi práctica, trato de usar NetworkInterface.getMTU()-40 para establecer el tamaño de la memoria intermedia de DatagramSocket.setSendBufferSize(). Por lo tanto, tratando de no confiar en getSendBufferSize() Esto es para asegurarse de que coincide con diferentes tamaños de ventana en diferentes plataformas y es universalmente aceptable en ethernet (ignorando el acceso telefónico por un momento). No lo he codificado en 1460 bytes (1500-20-20) porque en Windows, el tamaño de la MTU es universalmente 1500. Sin embargo, el tamaño de ventana de la propia plataforma de Windows es de 8192 bytes, pero creo que al establecer SO_SNDBUF en < MTU, Estoy cargando menos la capa de red/IP, y para todos los saltos de enrutadores y receptores, algunos gastos generales. Por lo tanto, reduciendo un poco de latencia en la red.

De forma similar, para el búfer de recepción, estoy utilizando un máximo de 64K o 65535 bytes. De esta manera, mi programa es portátil en diferentes plataformas usando diferentes tamaños de ventana.

¿Crees que suena bien? No he implementado ninguna herramienta para medir las diferencias, pero supongo que es el caso basado en lo que hay por ahí.

+0

No tiene sentido establecer un tamaño de búfer pequeño. No está 'cargando menos la capa de IP de la red' o 'reduciendo algo de latencia'. Hazlo grande, o simplemente déjalo en paz si no sabes lo que estás haciendo. Pero asegúrese de no * enviar * nada demasiado grande. No hay 'tamaño de ventana' en UDP. ¿Te refieres a MTU? – EJP

+0

@EJP. Hay muchas publicaciones en la web que mencionan claramente que la fragmentación agrega gastos generales a la red/enrutadores. Consulte http://pedrotrigueira.net/?page_id=163 como un ejemplo. AL establecer el tamaño de SO_SNDBUF <= MTU, está evitando esa sobrecarga de fragmentación y reensamblaje. Tiene razón en que UDP no tiene que lidiar con el tamaño de la ventana de la plataforma en la capa de transporte, pero si el paquete es más grande que el tamaño de la ventana de la plataforma, se entregaría truncado a la capa de transporte. Entonces, no puedes enviar un paquete de 64K. – Ashley

+1

Al configurar 'SO_SNDBUF <= MTU', se está evitando el envío de datagramas más grandes, pero también está evitando que el UDP almacene los datagramas salientes, incluso si son de un tamaño aceptable y bloquean su código de envío indebidamente. Es el * tamaño de 'send()' * que determina el tamaño del datagrama, y ​​debe mantener * that * EJP

Cuestiones relacionadas