Проблема с записью Java NIO SocketChannel

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

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

Что может быть причиной такого поведения? Могут ли внешние факторы, такие как оперативная память, ОС и т. д., вызывать помехи?

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

ИЗМЕНИТЬ:

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


person Nilesh    schedule 27.04.2010    source источник


Ответы (2)


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

Ваши ожидания неверны.

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

person user207421    schedule 27.04.2010

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

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

person Buchi    schedule 14.06.2011