java - socket - Tamaño máximo del búfer de envío/recepción de DatagramPacket(UDP)
sockets tcp udp java (2)
En Java al usar el DatagramPacket
suponga que tiene un búfer de byte[1024*1024]
. Si acaba de pasar eso por el DatagramPacket al enviar / recibir, ¿Java recibirá una llamada para el bloque DatagramPacket hasta que haya leído el megabyte completo?
Estoy preguntando si Java lo dividirá o simplemente tratará de enviar todo lo que se caiga.
Normalmente, el límite de tamaño es de alrededor de 64 KB para un paquete UDP, pero me pregunto, ya que la API de Java permite matrices de bytes si ese es un límite y algo super enorme se elimina o se divide y se vuelve a ensamblar para usted.
Si se descarta, ¿qué llamada de API me indicaría la carga útil máxima de datos que puedo usar en la llamada de Java? He escuchado que IPv6 también tiene marcos jumbo, pero ¿admite DatagramPacket (o DatagramSocket
) que desde UDP define la especificación del encabezado?
@ Mihai Danila. Como no pude agregar un comentario a la respuesta anterior, es por eso que escribo en la sección de respuestas.
En la continuación de su respuesta sobre el tamaño de MTU, en mi práctica, trato de usar NetworkInterface.getMTU()-40
para configurar el tamaño del búfer de DatagramSocket.setSendBufferSize()
. Entonces, tratando de no confiar en getSendBufferSize()
Esto es para asegurarse de que coincida con diferentes tamaños de ventana en diferentes plataformas y sea universalmente aceptable en Ethernet (ignorando el acceso telefónico por un momento). No lo he codificado a 1460 bytes (1500-20-20) porque en Windows, el tamaño de MTU es universalmente de 1500. Sin embargo, el tamaño de la ventana de la plataforma de Windows es de 8192 bytes, pero creo que, al establecer el SO_SNDBUF en <MTU, Estoy cargando menos la capa de red / IP, y para todos los saltos de enrutadores y receptores, algunos gastos generales. De esta forma, se reduce algo de latencia en la red.
Del mismo modo, para el búfer de recepción, estoy usando un máximo de 64 K o 65535 bytes. De esta manera mi programa es portátil en diferentes plataformas utilizando diferentes tamaños de ventana.
¿Crees que suena bien? No he implementado ninguna herramienta para medir las diferencias, pero supongo que es el caso en función de lo que hay por ahí.
DatagramPacket
es solo 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 se garantiza que solo se enrutan 576 bytes. En cualquier ruta de red dada, 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 dividirá automáticamente el datagrama en fragmentos y los reensamblará al final, pero solo hasta 64 kilobytes y solo si todos los fragmentos lo logran. Si se pierde algún fragmento, o si algún dispositivo decide que no le gustan los fragmentos, se pierde todo el paquete.
Como se señaló anteriormente, es imposible saber de antemano cuál será el MTU de la ruta. Existen varios algoritmos para experimentar, pero muchos dispositivos no implementan adecuadamente (o ignoran deliberadamente) los estándares necesarios, por lo que todo se reduce a prueba y error. O simplemente 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, debe obtener un error EMSGSIZE
o su equivalente. Si envía menos que eso pero más de lo que permite la red, el paquete simplemente desaparecerá.