ReadableByteChannel.read (ByteBuffer dest) считывает с ограничением в 8 КБ.Почему?

StackOverflow https://stackoverflow.com/questions/3718464

Вопрос

У меня есть кое-какой код, который:

  1. считывает из ReadableByteChannel в ByteBuffer,
  2. принимает к сведению переданные байты,
  3. делает паузу от нескольких десятков до сотен миллисекунд,
  4. передает ByteBuffer на WritableByteChannel.

Некоторые детали:

  • Оба канала являются сокетами TCP / IP.
  • Общий объем считываемых данных по соединению исчисляется десятками мегабайт.
  • Исходный сокет (который ReadableByteChannel получает байты от) находится на том же компьютере.
  • 64-разрядный Debian Lenny на HP DL380s
  • Sun Java 1.6.0 обновление 20

Проблема в том, что независимо от того, насколько велик байтебуфер, либо с .allocate() или .allocateDirect(), количество байт, считываемых в байт-буфер, достигает максимума в 8 КБ.Мой целевой размер ByteBuffer составляет 256 КБ, что составляет лишь крошечную долю (1/32-ю).Примерно в 10% случаев считывается только 2896 байт.

Я проверил настройки TCP-буфера операционной системы, и они выглядят нормально.Это подтверждается просмотром отчета netstat о том, сколько байт находится в буфере - у обоих есть данные в буферах сокетов, превышающие 8 КБ.

tcp        0 192384 1.2.3.4:8088     1.2.3.4:53404    ESTABLISHED
tcp6  110144      0 1.2.3.4:53404    1.2.3.4:8088     ESTABLISHED

Одна вещь, которая выделяется здесь, - это сочетание TCP и TCP6, но, я думаю, это не должно быть проблемой.Мой Java-клиент находится на порту 53404 в приведенном выше выводе.

Я попытался настроить свойства сокета в пользу пропускной способности, а не задержки, но без изменений.

Socket socket = new Socket(host.getHostName(), host.getPort());
socket.setPerformancePreferences(1, 0, 2);  //bw > connection time > latency

Когда я регистрирую значение socket.getReceiveBufferSize(), он последовательно сообщает всего лишь 43856 байт.Хотя он меньше, чем мне бы хотелось, он все равно больше 8 КБ.(Это также не очень круглое число, которого я бы ожидал.)

Я действительно в тупике относительно того, в чем здесь проблема.Теоретически, AFAIK, этого не должно было происходить.Было бы нежелательно "переходить" к решению, основанному на потоке, хотя именно к этому мы перейдем дальше, если решение не может быть найдено.

Что я упускаю из виду?Что я могу сделать, чтобы это исправить?

Это было полезно?

Решение

Хорошо, я нашел проблему!(И я отвечаю на свой собственный вопрос на случай, если у кого-то возникнет такая же проблема.)

Я приводил в пример ReadableByteChannel не непосредственно из Socket экземпляр, но из HttpEntity.getContent() (Клиент Apache HTTP Commons для Общего доступа) возвращенный метод InputStream.Клиенту HTTP Commons был передан сокет на ранней стадии вместе с DefaultHttpClientConnection.bind() способ.Чего я не понял, так это того, что, по-моему, канал имеет BufferedInputStream экземпляр, скрытый внутри клиентской реализации HTTP Commons.(8 КБ просто является значением по умолчанию для Java 6.)

Таким образом, мое решение состояло в том, чтобы захватить ReadableByteChannel с самого начала Socket пример.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top