2012-02-08 23 views
15

W języku Java podczas używania DatagramPacket załóżmy, że masz bufor o wartości byte[1024*1024]. Jeśli po prostu przekazujesz to dla DatagramPacket podczas wysyłania/odbierania, Java odbierze połączenie do bloku DatagramPacket, dopóki nie przeczyta całego megabajta?Maksymalny rozmiar bufora wysyłania/przywracania protokołu Java DatagramPacket (UDP):

Pytam, czy Java go podzieli lub po prostu spróbuje wysłać całą rzecz, która zostanie upuszczona.

Zwykle limit rozmiaru wynosi około 64 KB dla pakietu UDP, ale zastanawiałem się, ponieważ interfejs API języka Java zezwala na tablice bajtowe, jeśli jest to limit, a coś bardzo dużego jest upuszczane lub dzielone i ponownie składane.

Po upuszczeniu, jakie wywołanie API powie mi, jaki maksymalny ładunek danych mogę użyć w wywołaniu Java? Słyszałem, że IPv6 ma również ramki jumbo, ale czy obsługuje DatagramPacket (lub DatagramSocket), ponieważ UDP definiuje specyfikację nagłówka?

Odpowiedz

23

DatagramPacket to tylko opakowanie w gnieździe opartym na protokole UDP, więc obowiązują zwykłe reguły UDP.

64 kilobajtów to teoretyczny maksymalny rozmiar kompletnego datagramu IP, ale gwarantowane jest tylko 576 bajtów. Na dowolnej danej ścieżce sieciowej łącze z najmniejszą jednostką maksymalnej transmisji określi rzeczywisty limit. (1500 bajtów, mniej nagłówków jest wspólnym maksimum, ale nie można przewidzieć, ile nagłówków będzie tam, więc najbezpieczniej ograniczyć wiadomości do około 1400 bajtów.)

Jeśli przekroczysz limit MTU, IPv4 zostanie automatycznie rozbić datagram na fragmenty i ponownie złożyć je na końcu, ale tylko do 64 kilobajtów i tylko wtedy, gdy przejdą wszystkie fragmenty. Jeśli jakikolwiek fragment zostanie utracony lub jeśli jakieś urządzenie zdecyduje, że nie lubi fragmentów, wówczas cały pakiet zostanie utracony.

Jak wspomniano powyżej, nie można z góry określić, jaka będzie wartość MTU ścieżki. Istnieją różne algorytmy do eksperymentowania, aby dowiedzieć się, ale wiele urządzeń nie implementuje prawidłowo (lub celowo ignoruje) niezbędnych standardów, więc wszystko sprowadza się do prób i błędów. Lub po prostu zgadnij 1400 bajtów na wiadomość.

Jeśli chodzi o błędy, jeśli spróbujesz wysłać więcej bajtów niż pozwala na to system operacyjny, powinieneś otrzymać błąd EMSGSIZE lub jego odpowiednik. Jeśli wyślesz mniej, ale więcej niż pozwala na to sieć, pakiet zniknie.

+1

W rzeczywistości minimalna gwarantowana wartość MTU dla IPv4 w sieci to tylko 68 bajtów - 576 to minimum, które hosty muszą obsługiwać. Tak czy inaczej, taki mały MTU będzie naprawdę, naprawdę niezwykły. – lxgr

+0

Czy to oznacza, że ​​jeśli masz pakiet większy niż 64 KB, używałbyś innego protokołu? –

+0

@PhaniRahul: Powiedziałbym, że to znaczy "dziękuję Bogu, że protokół obsługuje przezroczystość segmentacji i sprawia, że ​​moje dane są na tyle pakietów, ile potrzeba". Wątpię, aby jakiekolwiek praktyczne protokoły w użyciu dały większe rozmiary pakietów. :) –

-1

@ Mihai Danila. Ponieważ nie mogłem dodać komentarza do powyższej odpowiedzi, dlatego piszę do sekcji odpowiedzi.

Kontynuując odpowiedź na temat rozmiaru MTU, w mojej praktyce próbuję użyć NetworkInterface.getMTU()-40 do ustawienia rozmiaru bufora DatagramSocket.setSendBufferSize(). Tak więc, próbując nie polegać na getSendBufferSize() Ma to na celu upewnienie się, że pasuje do różnych rozmiarów okien na różnych platformach i jest ogólnie akceptowalne w sieci Ethernet (ignorując przez chwilę połączenie dial-up). Nie zakodowałem go na stałe do 1460 bajtów (1500-20-20), ponieważ w systemie Windows rozmiar jednostki MTU to 1500. Jednak rozmiar okna Windows wynosi 8192 bajtów, ale uważam, że ustawiając SO_SNDBUF na < MTU, Obciążam warstwę sieci/IP mniej, a dla wszystkich przeskoków dla routerów i odbiorników, pewne koszty ogólne. W ten sposób zmniejszając pewne opóźnienia w sieci.

Podobnie, w przypadku bufora odbiorczego używam maksimum 64 KB lub 65535 bajtów. W ten sposób mój program jest przenośny na różnych platformach przy użyciu różnych rozmiarów okien.

Czy uważasz, że to brzmi OK? Nie zaimplementowałem żadnych narzędzi do mierzenia różnic, ale zakładając, że jest to oparte na tym, co tam jest.

+0

Nie ma sensu ustawianie małego rozmiaru bufora. Nie obciążasz w mniejszym stopniu warstwy IP sieci lub w ogóle nie zmniejszasz opóźnień. Ustaw to na duże, lub po prostu zostaw to w spokoju, jeśli nie wiesz, co robisz. Ale upewnij się, że nie przesyłasz * niczego zbyt dużego. W UDP nie ma "rozmiaru okna". Masz na myśli MTU? – EJP

+0

@EJP. Istnieje wiele postów w Internecie, które wyraźnie wskazują, że fragmentacja dodaje do sieci/routerów. Sprawdź http://pedrotrigueira.net/?page_id=163 jako przykład. Ustawiając rozmiar SO_SNDBUF <= MTU, unikasz narzutów związanych z fragmentacją i ponownym montażem. Masz rację, że UDP nie musi zajmować się wielkością okna platformy w warstwie transportowej, ale jeśli pakiet jest większy niż rozmiar okna platformy, zostanie dostarczony jako obcięty do warstwy transportowej. Więc nie możesz wysłać pakietu 64 KB. – Ashley

+1

Ustawiając 'SO_SNDBUF <= MTU', uniemożliwiasz sobie wysyłanie datagramów większych, ale także uniemożliwiasz UDP buforowanie wychodzących datagramów, nawet jeśli mają one akceptowalny rozmiar, a tym samym niepotrzebnie blokują twój kod wysyłania. Jest to * rozmiar 'send()' *, który określa rozmiar datagramu i powinieneś zachować * to * EJP

Powiązane problemy