Есть сервер, на Java, работающий на асинхронных сокетах. Код сервера, примерно, такой
class ClientHandler implements CompletionHandler<Integer, ByteBuffer> {
private final AsynchronousSocketChannel socket;
private static final writer = new WriteHandler();
public ClientHandler(AsynchronousSocketChannel socket) {
this.socket = socket;
doRead();
}
private void doRead() {
ByteBuffer buf = ByteBuffer.allocate(PACKET_SISE);
socket.read(buf, buf, this);
}
private ByteBuffer process(ByteBuffer data) {
.........
}
@Override
public void completed(Integer result, ByteBuffer attachment) {
if (attachment.hasRemaining()) {
socket.close();
return;
}
ByteBuffer buf = process(attachment);
socket.write(buf, buf, writer);
doRead();
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
exc.printStackTrace();
}
}
class WriteHandler implements CompletionHandler<Integer, ByteBuffer> {
@Override
public void completed(Integer result, ByteBuffer attachment) {
if (attachment.hasRemaining())
socket.close();
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
exc.printStackTrace();
}
}
Т.е. алгоритм простой - ждем пакета, определенной длины, обрабатываем его и отправляем результат.
И есть Win32 клиент, который работает на блокирующем сокете по такой схеме
while (data = getData()) {
send(socket, &data, sizeof(data), 0);
recv(socket, &data, sizeof(data), 0);
}
Сформировали новій пакет, отправили его, дождались результата, формируем новій пакет. Время формирования пакета очень мало.
Так, вот, уже на пятом-шестом пакете вызов на сервере socket.write(buf, buf, writer);
приводит к исключению WritePendingException
.
Я понимаю, что это за исключение и понимаю как с ним бороться. Я не понимаю как оно может возникнуть? Чтобы оно возникло, я должен записать в сокет данные до того, как отправились предыдущие. Но повторная запись возможна только при получении нового пакета, а это значит, что ответ по предыдущему пакету уже дошел до клиента и был обработан.
Такое ощущение, что в классе AsynchronousSocketChannel
не синхронизирован метод write()
в результате чего между отправкой данных и снятием флага writePending
вклинивается обработка нового пакета
Этот флаг сбрасывается перед вызовом коллбэка completion
. Поэтому вариантов решения проблемы два
completion
Виртуальный выделенный сервер (VDS) становится отличным выбором
Есть CRUD API к EntityEntity имеет поля id и someString Состоит из трех слоев : Controller, Service, Repository Естественно контроллер знает только о сервисе, а сервис только...
У меня есть CustomView который рисует текст по ширинеНа андроиде 7
Добрый день помогите разобраться с запросамиЕсть два JSON
С рекурсией решается быстрее, если искать до 21 числа, а вот все что больше уже намного быстрее решается простым сложениемПочему с рекурсией...