Проблема записи Java NIO SocketChannel - PullRequest
2 голосов
/ 27 апреля 2010

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

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

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

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

РЕДАКТИРОВАТЬ:

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

Ответы [ 2 ]

1 голос
/ 14 июня 2011

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

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

1 голос
/ 27 апреля 2010

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

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

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

...