Как некоторый фон:
У меня есть подключение к серверу с SocketChannel, SelectionKey... и т.д. На стороне клиента, если я хочу отправить что-то на сервер, я просто записываю свои данные в ByteBuffer и отправляю их через канал сокета. Если все это было написано, я закончил и могу вернуться к OP_READ. Если не все было записано, я беру оставшиеся байты, сохраняю их где-нибудь в буфере «для отправки» и помечаю ключ OP_WRITE (можно ли заменить OP_READ, чтобы он только писал?).
Поэтому в следующий раз, когда я вызову selectNow(), я предполагаю, что он распознает OP_WRITE и попытается сбросить больше данных (что я попытаюсь сделать, введя еще один цикл записи с данными для записи и повторив предыдущий при необходимости). ).
Это приводит меня к двум вопросам:
- Должен ли я оставить его в OP_WRITE, пока все данные не будут сброшены? Или мне следует перейти на OP_READ и попытаться выполнить любое промежуточное чтение?
Если канал записи заполнен, и я не могу писать, мне просто продолжать зацикливаться, пока я не начну писать? Если соединение внезапно прерывается, я не уверен, должен ли я просто написать то, что могу, вернуться к OP_READ, попытаться прочитать, а затем вернуться к OP_WRITE. Из того, что я читал, кажется, что это неправильный способ делать что-то (и может вызвать большие накладные расходы, постоянно переключаясь туда и обратно?).
- Каков оптимальный способ обработки чтения и записи больших объемов данных, когда оба буфера могут быть заполнены?
Чтение звучит просто, потому что вы просто выполняете цикл до тех пор, пока данные не будут использованы, но с записью... сервер может только писать, а не читать. Это оставило бы вас с довольно полным буфером отправки, и бесконечное циклирование на OP_WRITE без чтения было бы плохо. Как избежать такой ситуации? Вы устанавливаете таймер, по которому вы просто прекращаете попытки записи и снова начинаете чтение, если буфер отправки не очищается? Если да, то удаляете ли вы OP_WRITE и запоминаете его на потом?
Дополнительный вопрос: вам вообще нужен OP_READ для чтения из сети? Я не уверен, похоже ли это на OP_WRITE, где вы отмечаете его только в конкретном случае (на всякий случай, если я делаю это неправильно, так как он у меня на OP_READ в 99,9% случаев).
В настоящее время я просто устанавливаю свой ключ в OP_READ, а затем оставляю его в этом режиме, ожидая данных, а затем перехожу к OP_WRITE тогда и только тогда, когда при записи не удается отправить все данные (со значением write () равным 0).
selectNow()
, но неSelector
, а толькоSocketChannel
, так что я немного запутался, какого черта вы делаете. - person markspace   schedule 22.06.2015selectNow()
без селектора? На некоторые из моих вещей можно ответить, даже не нуждаясь в коде, поскольку вторая половина является чисто концептуальной. - person Water   schedule 22.06.2015