2012-02-08 18 views
15

In Java quando si utilizza DatagramPacket, si supponga di disporre di un buffer byte[1024*1024]. Se lo passi per il DatagramPacket quando invii/ricevi una chiamata di ricezione Java per il blocco DatagramPacket fino a quando non ha letto l'intero megabyte?Java DatagramPacket (UDP) dimensione massima del buffer di invio/ricezione

Mi chiedo se Java lo dividerà o semplicemente cercherò di inviare l'intera cosa che viene rilasciata.

Normalmente il limite di dimensione è di circa 64 KB per un pacchetto UDP, ma mi chiedevo poiché l'API di Java consente gli array di byte se questo è un limite e qualcosa di super enorme viene eliminato o suddiviso e riassemblato per te.

Se viene interrotta quale chiamata API mi dirà il massimo carico utile di dati che posso utilizzare nella chiamata Java? Ho sentito che IPv6 ha anche frame jumbo, ma DatagramPacket (o DatagramSocket) supporta quello dal momento che UDP definisce le specifiche dell'header?

risposta

23

DatagramPacket è solo un wrapper su un socket UDP, quindi si applicano le normali regole UDP.

64 kilobyte è la dimensione massima teorica di un datagramma IP completo, ma è possibile instradare solo 576 byte. Su un determinato percorso di rete, il collegamento con l'unità di trasmissione massima più piccola determinerà il limite effettivo. (1500 byte, meno intestazioni è il massimo comune, ma è impossibile prevedere quante intestazioni sarà così più sicuro limitare i messaggi a circa 1400 byte.)

Se si supera il limite MTU, IPv4 verrà automaticamente rompere il datagramma in frammenti e rimontarli alla fine, ma solo fino a 64 kilobyte e solo se tutti i frammenti lo superano. Se un frammento viene perso o se un dispositivo decide che non gli piacciono i frammenti, l'intero pacchetto viene perso.

Come indicato sopra, è impossibile sapere in anticipo quale sarà la MTU del percorso. Ci sono vari algoritmi da sperimentare per scoprirlo, ma molti dispositivi non implementano (o ignorano deliberatamente) correttamente gli standard necessari, quindi tutto si riduce a tentativi ed errori. Oppure puoi solo indovinare 1400 byte per messaggio.

Per quanto riguarda gli errori, se si tenta di inviare più byte rispetto al sistema operativo configurato per consentire, è necessario ottenere un errore EMSGSIZE o equivalente. Se invii meno di quello, ma più di quanto permetta la rete, il pacchetto sparirà.

+1

In realtà, l'MTU minimo garantito per IPv4 attraverso la rete è di soli 68 byte - 576 è il minimo che gli host devono gestire. Ad ogni modo, un MTU così piccolo sarebbe davvero, davvero insolito. – lxgr

+0

Significa che se si ha una dimensione del pacchetto maggiore di 64 KB, si utilizzerà un protocollo diverso? –

+0

@PhaniRahul: Direi che significa "grazie a Dio che il protocollo gestisce la segmentazione in modo trasparente e rende i miei dati in tutti i pacchetti necessari". Dubito che eventuali protocolli pratici in uso ti offriranno pacchetti di dimensioni maggiori. :) –

-1

@ Mihai Danila. Perché non ho potuto aggiungere un commento alla risposta di cui sopra, ecco perché scrivere nella sezione di risposta.

In seguito alla risposta sulla dimensione MTU, nella mia pratica, provo a utilizzare NetworkInterface.getMTU()-40 per impostare la dimensione del buffer di DatagramSocket.setSendBufferSize(). Quindi, cercando di non fare affidamento su getSendBufferSize() Questo per assicurarsi che corrisponda a dimensioni di finestre diverse su piattaforme diverse ed è universalmente accettabile su Ethernet (ignorando la connessione remota per un momento). Non ho hardcoded a 1460 byte (1500-20-20) perché su Windows, la dimensione MTU è universalmente 1500. Tuttavia, la dimensione della finestra della piattaforma Windows è 8192 byte, ma credo, impostando il SO_SNDBUF su MTU <, Sto gravando meno sul livello di rete/IP e su tutti gli hop per router e ricevitori, alcuni costi generali. Quindi, riducendo un po 'di latenza sulla rete.

Analogamente, per il buffer di ricezione, sto utilizzando un massimo di 64 K o 65535 byte. In questo modo il mio programma è portatile su piattaforme diverse che usano finestre di dimensioni diverse.

Pensi che suoni OK? Non ho implementato alcun strumento per misurare eventuali differenze, ma assumendo che sia il caso basato su ciò che è là fuori.

+0

Non ha senso impostare una piccola dimensione del buffer. Non stai affatto "caricando il livello IP della rete meno" o "riducendo la latenza". Impostalo in grande, o lascialo solo se non sai cosa stai facendo. Ma assicurati di non inviare * qualcosa di troppo grande. Non c'è "dimensione della finestra" in UDP. Intendi MTU? – EJP

+0

@EJP. Ci sono molti post sul web che menzionano chiaramente che la frammentazione aggiunge un sovraccarico alla rete/router. Controlla http://pedrotrigueira.net/?page_id=163 come esempio. Impostando la dimensione di SO_SNDBUF <= MTU, si evita il sovraccarico di frammentazione e riassemblaggio. Hai ragione che UDP non ha a che fare con le dimensioni della piattaforma della piattaforma al livello di trasporto, ma se il pacchetto è più grande della dimensione della finestra della piattaforma, verrebbe consegnato troncato al livello di trasporto. Quindi, non puoi inviare un pacchetto da 64K. – Ashley

+1

Impostando 'SO_SNDBUF <= MTU' ci si impedisce di inviare datagrammi di dimensioni maggiori, ma si impedisce anche a UDP di eseguire il buffering dei datagrammi in uscita, anche se di dimensioni accettabili, e quindi di bloccare indebitamente il proprio codice di invio. È la * dimensione di 'send()' * che determina la dimensione del datagramma, e dovresti mantenere * that * EJP

Problemi correlati