Почему java.nio.SocketChannel не отправляет данные (Jdiameter)?

Я создаю клиент и сервер простого диаметра (Ссылка на источники). Клиент должен отправить 10000 сообщений ccr, но в wireshark я вижу, что будет отправлено только ~ 300 сообщений ccr. Другие сообщения приводили к превышению времени ожидания на клиенте. Я запускаю сервер и клиент на разных компьютерах с Windows 7. Я нашел в источниках JDiameter строка, где jdiameter отправляет ccr (строка 280), и я думаю, что в случае отправки буфера сокета полная копия не отправлена. Я добавляю перед строкой 280 этот код

while(bytes.hasRemaining())

Клиент отправляет ~9900 ccr, но очень медленно. Я протестировал клиент на сервере другого диаметра, написанном на c++, клиент (на jdiameter без моих изменений) отправляет ~7000 ccr, но этот сервер размещен на debian.

Я не знаю способов решить эту проблему, спасибо за любую помощь.


person MadCrank    schedule 18.03.2014    source источник


Ответы (1)


Если отправка отправителя возвращает ноль, это означает, что буфер отправки сокета отправителя заполнен, что, в свою очередь, означает, что буфер приема сокета получателя заполнен, что, в свою очередь, означает, что получатель читает медленнее, чем отправитель отправляет.

Так что ускорьте приемник.

NB В неблокирующем режиме просто зацикливаться на вызове write(), пока он возвращает ноль, недостаточно. Если write() возвращает ноль, вы должны:

  1. Отмените регистрацию канала для OP_READ и зарегистрируйте его для OP_WRITE
  2. Вернитесь к циклу выбора.
  3. Когда сработает OP_WRITE, повторите запись. На этот раз, если он не возвращает ноль, отмените регистрацию OP_WRITE и (возможно, в соответствии с вашими требованиями) зарегистрируйте OP_READ.

Обратите внимание, что держать канал все время зарегистрированным для OP_WRITE тоже неправильно. Канал сокета почти всегда доступен для записи, то есть в буфере отправки сокета почти всегда есть место. Что вас интересует, так это переход между не-доступным для записи и доступным для записи.

person user207421    schedule 18.03.2014
comment
Я увеличиваю буферы сокетов для приема и отправки до 1 МБ в TcpTransportClient.intialize: socketChannel.socket().setReceiveBufferSize(size); socketChannel.socket().setSendBufferSize(размер); И добавьте этот код в sendMessage: rc = socketChannel.write(bytes); if (rc == 0) while (bytes.hasRemaining()) { Thread.sleep(10l); rc = socketChannel.write(bytes); } Он отлично работает с сервером диаметра на С++ в Debian, но проблема с сервером jdiameter не решена. - person MadCrank; 20.03.2014
comment
@MadCrank Увеличение размера буфера не ускоряет работу приемника, а только отсрочивает проблему. Вы не разместили свой исходный код, но ни while (bytes.hasRemaining()), ни while (rc < bytes.array().length), которые я нашел по вашей ссылке, не являются правильным способом записи в NIO. - person user207421; 15.10.2014
comment
Нужно ли отменять регистрацию OP_READ? - person mike; 10.02.2015
comment
@mike Это не обязательно, но нет особого смысла читать новые данные, если вы не можете записать старые данные. Позвольте пиру застопориться, а не пытаться читать все новое, что он вам отправляет, заполняя ваши собственные буферы чтения и т. д. - person user207421; 26.01.2016