Неблокирующая розетка с TCP - PullRequest
0 голосов
/ 28 декабря 2010

Я пишу программу с использованием неблокирующего сокета Java и TCP.Я понимаю, что TCP является потоковым протоколом, но протокол IP нижнего уровня использует пакеты.Когда я вызываю SocketChannel.read (ByteBuffer dst), всегда ли я получу весь контент IP-пакетов?или это может закончиться в любой позиции в середине пакета?

Это имеет значение, потому что я пытаюсь отправлять отдельные сообщения через канал, каждое сообщение достаточно маленькое, чтобы его можно было отправить в одном IP-пакете безфрагментирован.Было бы здорово, если бы я всегда мог получить целое сообщение, вызвав read () на стороне получателя, в противном случае мне придется реализовать какой-то метод для повторной сборки сообщений.

Редактировать: предположим, что на отправителеКроме того, сообщения отправляются с большим интервалом (например, 1 секунда), поэтому они не собираются группироваться в один IP-пакет.На стороне получателя буфер, используемый для вызова read (ByteBuffer dst), достаточно велик для хранения любого сообщения.

Ответы [ 3 ]

2 голосов
/ 28 декабря 2010

TCP - это поток байтов.Каждое чтение получит от 1 до максимального размера предоставленного вами буфера и количества байтов, доступных для чтения в это время.

TCP ничего не знает о вашей концепции сообщений.Каждая отправка клиентом может привести к 0 или более операций чтения на другом конце.Ноль или более, потому что вы можете получить одно чтение, которое возвращает более одного из ваших «сообщений».

Вы должны ВСЕГДА писать свой код чтения, чтобы он мог обрабатывать кадры вашего сообщения и либо собирать частичные сообщения, либо разбивать их на части.несколько.

Вы можете обнаружить, что если вы не беспокоитесь об этой сложности, то ваш код будет «работать» большую часть времени, не полагайтесь на это.Как только вы работаете в загруженной сети или через Интернет, или как только вы увеличите размер своих сообщений, вы будете укушены из-за испорченного кода.

Я еще немного расскажу о формировании TCP-сообщения здесь: http://www.serverframework.com/asynchronousevents/2010/10/message-framing-a-length-prefixed-packet-echo-server.html и здесь: http://www.serverframework.com/asynchronousevents/2010/10/more-complex-message-framing.html, хотя это с точки зрения реализации C ++, поэтому может представлять или не интересовать вас.

1 голос
/ 28 декабря 2010

API сокетов не гарантирует, что вызовы send () и recv () соотносятся с дейтаграммами для сокетов TCP. На отправляющей стороне все может быть перегруппировано, например, система может отложить отправку одной дейтаграммы, чтобы увидеть, имеет ли приложение больше данных; на принимающей стороне вызов чтения может извлечь данные из нескольких дейтаграмм или частичной дейтаграммы, если размер, указанный вызывающей стороной, требует разрыва пакета.

IOW, API сокетов TCP предполагает, что у вас есть поток байтов, а не последовательность пакетов. Вы должны убедиться, что продолжаете вызывать read (), пока у вас не будет достаточно байтов для запроса.

0 голосов
/ 28 декабря 2010

Из документации SocketChannel:

A socket channel in non-blocking mode, for example, cannot read 
any more bytes than are immediately available from the socket's input buffer;

Таким образом, если целевой буфер достаточно велик, предполагается, что вы сможете использовать все данные во входном буфере сокета.

...