2010-04-27 2 views
2

Я использую SocketChannel для Java NIO для записи: int n = socketChannel.write(byteBuffer); Большую часть времени данные отправляются в одной или двух частях; то есть, если данные не могут быть отправлены в одном аттестате, оставшиеся данные будут повторены.Проблема с написанием Java NIO SocketChannel

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

В чем может быть причина такого поведения? Могут ли внешние факторы, такие как ОЗУ, ОС и т. Д. Вызывать хиндикацию?

Пожалуйста, помогите мне решить эту проблему. Если какая-либо другая информация требуется, пожалуйста, дайте мне знать. Благодаря

EDIT:

Есть ли способ в NIO SocketChannel, чтобы проверить, если канал может быть обеспечен с данными, чтобы написать до фактического написания. Цель состоит в том, что после попытки записи полных данных, если некоторые данные не были записаны на канале, перед записью оставшихся данных мы можем проверить, может ли SocketChannel получить больше данных; поэтому вместо того, чтобы пытаться несколько раз бесплодно, поток, ответственный за запись этих данных, мог подождать или сделать что-то еще.

+0

Можете ли вы разместить код? –

ответ

1

TCP/IP - это протокол потоковой передачи. На любом уровне нет никакой гарантии, что отправленные вами данные не будут разбиты на однобайтные сегменты или что-нибудь среднее между этим и отдельным сегментом, как вы его написали.

Ваши ожидания неуместны.

Re EDIT, write() будет возвращать ноль при заполнении буфера отправки сокета. Когда вы это получите, зарегистрируйте канал для OP_WRITE и остановите цикл записи. Когда вы получите OP_WRITE, отмените регистрацию (очень важно) и продолжайте писать. Если write() снова возвращает ноль, повторите.

1

При использовании TCP мы можем писать по каналу со стороны канала отправителя только до тех пор, пока буферы сокета не будут заполнены, а не после этого. Таким образом, если приемник медленно потребляет данные, буферы сокетов отправителя заполняются, и, как вы упомянули, write() может возвращать ноль.

В любом случае, когда на стороне отправителя есть данные, мы должны зарегистрировать SocketChannel с селектором с OP_WRITE в качестве заинтересованной операции, а когда селектор возвращает SelectionKey, проверьте key.isWritable() и попробуйте запись на этом канале. Как упоминалось выше в Nilesh, не забудьте отменить регистрацию бит OP_WRITE с помощью селектора после записи полных данных.