2012-02-08 48 views
15

Trong Java khi sử dụng DatagramPacket giả sử bạn có bộ đệm byte[1024*1024]. Nếu bạn chỉ cần vượt qua điều đó cho DatagramPacket khi gửi/nhận sẽ một Java nhận cuộc gọi cho khối DatagramPacket cho đến khi nó đã đọc toàn bộ megabyte?Java DatagramPacket (UDP) tối đa gửi/recv đệm kích thước

Tôi hỏi nếu Java sẽ chia nhỏ hoặc chỉ cố gắng gửi toàn bộ nội dung bị xóa.

Thông thường giới hạn kích thước là khoảng 64KB cho gói UDP, nhưng tôi tự hỏi vì API của Java cho phép mảng byte nếu đó là giới hạn và thứ gì đó cực lớn bị bỏ hoặc chia nhỏ và ghép lại cho bạn.

Nếu bỏ cuộc gọi API nào sẽ cho tôi biết tải trọng dữ liệu tối đa mà tôi có thể sử dụng trong cuộc gọi Java? Tôi đã nghe nói rằng IPv6 cũng có khung jumbo, nhưng không DatagramPacket (hoặc DatagramSocket) hỗ trợ rằng kể từ khi UDP xác định spec tiêu đề?

Trả lời

23

DatagramPacket chỉ là trình bao bọc trên ổ cắm dựa trên UDP, vì vậy các quy tắc UDP thông thường sẽ được áp dụng.

64 kilobyte là kích thước tối đa theo lý thuyết của một gói dữ liệu IP hoàn chỉnh, nhưng chỉ có 576 byte được đảm bảo định tuyến. Trên bất kỳ đường dẫn mạng cụ thể nào, liên kết với Đơn vị truyền tối thiểu nhỏ nhất sẽ xác định giới hạn thực tế. (1500 byte, tiêu đề ít hơn là mức tối đa chung, nhưng không thể dự đoán có bao nhiêu tiêu đề sẽ an toàn nhất để giới hạn thư đến khoảng 1400 byte.)

Nếu bạn vượt quá giới hạn MTU, IPv4 sẽ tự động chia datagram thành các mảnh và reassemble chúng vào cuối, nhưng chỉ lên đến 64 kilobyte và chỉ khi tất cả các mảnh vỡ làm cho nó thông qua. Nếu bất kỳ mảnh nào bị mất, hoặc nếu bất kỳ thiết bị nào quyết định nó không thích các mảnh vỡ, thì toàn bộ gói bị mất.

Như đã lưu ý ở trên, không thể biết trước MTU của đường đi là gì. Có nhiều thuật toán khác nhau để thử nghiệm để tìm hiểu, nhưng nhiều thiết bị không thực hiện đúng cách (hoặc cố tình bỏ qua) các tiêu chuẩn cần thiết để tất cả đều đi xuống để thử và sai. Hoặc bạn chỉ có thể đoán 1400 byte cho mỗi tin nhắn.

Vì lỗi, nếu bạn cố gửi nhiều byte hơn hệ điều hành được định cấu hình để cho phép, bạn sẽ gặp lỗi EMSGSIZE hoặc tương đương. Nếu bạn gửi ít hơn nhưng nhiều hơn mạng cho phép, gói sẽ biến mất.

+1

Trên thực tế, MTU được bảo đảm tối thiểu cho IPv4 trên mạng chỉ 68 Byte - 576 là số tối thiểu mà máy chủ được yêu cầu để xử lý. Dù bằng cách nào, một MTU nhỏ như vậy sẽ thực sự, thực sự khác thường. – lxgr

+0

Điều đó có nghĩa là nếu bạn có kích thước gói lớn hơn 64KB, bạn có sử dụng giao thức khác không? –

+0

@PhaniRahul: Tôi sẽ nói rằng nó có nghĩa là "cảm ơn Chúa rằng giao thức xử lý phân đoạn một cách minh bạch và làm cho dữ liệu của tôi thành nhiều gói như là cần thiết". Tôi nghi ngờ nếu bất kỳ giao thức thực tế trong sử dụng sẽ cung cấp cho bạn kích thước gói lớn hơn. :) –

-1

@ Mihai Danila. Bởi vì tôi không thể thêm nhận xét vào câu trả lời ở trên, đó là lý do tại sao viết vào phần trả lời.

Tiếp tục câu trả lời của bạn về kích thước MTU, trong thực tế của tôi, tôi cố gắng sử dụng NetworkInterface.getMTU()-40 để đặt kích thước bộ đệm là DatagramSocket.setSendBufferSize(). Vì vậy, cố gắng không dựa vào getSendBufferSize() Điều này là để đảm bảo nó phù hợp với các kích thước cửa sổ khác nhau trên các nền tảng khác nhau và được chấp nhận rộng rãi trên ethernet (bỏ qua quay số trong giây lát). Tôi đã không hardcoded nó đến 1460 byte (1500-20-20) vì trên cửa sổ, kích thước MTU là phổ 1500. Tuy nhiên, kích thước cửa sổ của nền tảng cửa sổ riêng là 8192 byte, nhưng tôi tin rằng, bằng cách thiết lập SO_SNDBUF để < MTU, Tôi đang gánh nặng lớp mạng/IP ít hơn và cho tất cả các bước nhảy cho các bộ định tuyến và bộ thu, một số chi phí. Vì vậy, giảm độ trễ trên mạng.

Tương tự, đối với bộ đệm nhận, tôi đang sử dụng tối đa 64K hoặc 65535 byte. Bằng cách này, chương trình của tôi có thể di chuyển trên các nền tảng khác nhau bằng cách sử dụng các kích thước cửa sổ khác nhau.

Bạn có nghĩ rằng âm thanh đó có ổn không? Tôi đã không thực hiện bất kỳ công cụ nào để đo lường bất kỳ sự khác biệt nào nhưng giả định rằng trường hợp của nó dựa trên những gì đang diễn ra ở đó.

+0

Không có điểm thiết lập kích thước bộ đệm nhỏ. Bạn không phải là 'gánh nặng lớp IP mạng ít hơn' hoặc 'giảm một số độ trễ' ở tất cả. Đặt nó lớn, hoặc chỉ để nó một mình nếu bạn không biết mình đang làm gì. Nhưng hãy chắc chắn rằng bạn không * gửi * bất cứ điều gì quá lớn. Không có 'kích thước cửa sổ' trong UDP. Bạn có nghĩa là MTU? – EJP

+0

@EJP. Có rất nhiều bài viết trên trang web đề cập rõ ràng rằng phân mảnh thêm phí vào mạng/bộ định tuyến. Kiểm tra http://pedrotrigueira.net/?page_id=163 làm ví dụ. Bằng cách thiết lập kích thước của SO_SNDBUF <= MTU, bạn sẽ tránh được phần trên của phân mảnh và reassembly. Bạn có quyền là UDP không phải đối phó với kích thước cửa sổ nền tảng ở tầng vận chuyển, nhưng nếu gói lớn hơn kích thước cửa sổ của nền tảng, nó sẽ được phân phối cắt ngắn để vận chuyển lớp. Vì vậy, bạn không thể gửi một gói 64K. – Ashley

+1

Bằng cách thiết lập 'SO_SNDBUF <= MTU', bạn đang ngăn cản việc gửi các gói dữ liệu lớn hơn, nhưng bạn cũng ngăn cản UDP khỏi việc gửi đi các gói dữ liệu đi ngay cả khi chúng có kích thước chấp nhận được và do đó chặn mã gửi của bạn không đúng. Nó là * kích thước của 'send()' * xác định kích thước của datagram, và bạn nên giữ * rằng * EJP

Các vấn đề liên quan