Как увеличить размер буфера отправки SocketChannel?

Я попытался увеличить размер буфера отправки SocketChannel. Я хочу отправить все байты в моем ByteBuffer только за одну операцию записи. Это мой код:

channel = SocketChannel.open(address);
ByteBuffer buf = ByteBuffer.wrap(channelBytes);
channel.socket().setSendBufferSize(buf.remaining());
channel.write(buf);

Даже если я вызову метод setSendBufferSize, сокет не отправит более 131071 байт. Как я могу сделать?

Приемник вот такой:

Конструктор

uplink = ServerSocketChannel.open();
uplink.socket().bind(new InetSocketAddress(UPLINK_PORT));
uplink.socket().setReceiveBufferSize(2*1024*1024);

Метод запуска

SocketChannel clientChannelUp = uplink.accept();
clientChannelUp.socket().setReceiveBufferSize(2*1024*1024);
clientChannelUp.socket().setSendBufferSize(2*1024*1024);
buffer = ByteBuffer.allocate(Short.MAX_VALUE*100);
clientChannelUp.read(buffer);
buffer.flip();

С циклом чтения и записи мой код таков:

передатчик

while(buf.hasRemaining()) {
    channel.write(buf);
}

получатель

int r = clientChannelUp.read(buffer);
while(r==131071) {
    r=clientChannelUp.read(buffer);
}
buffer.flip();

person Walter Bianchi    schedule 20.01.2015    source источник
comment
Как это на самом деле работает в зависимости от ОС. Вы можете вызвать getSendBufferSize, чтобы увидеть фактический размер буфера.   -  person Peter Lawrey    schedule 21.01.2015
comment
Если я вызову getSendBufferSize без предварительной установки, результат будет 8192. Но канал отправляет 131071 байт. я в замешательстве   -  person Walter Bianchi    schedule 21.01.2015
comment
Откуда вы знаете? С этим кодом вы не можете сказать, сколько было отправлено.   -  person user207421    schedule 21.01.2015
comment
Когда я вызываю read(buffer) в другом потоке, я вижу (в режиме отладки), что позиция буфера равна 131071.   -  person Walter Bianchi    schedule 21.01.2015
comment
Точно. Вы измерили получателя и обвиняете отправителя. Дело в том, что этот код отправляет все данные, но буфер вашего сокета receive на узле содержит только 131071 байт. В режиме блокировки отправка блокируется до тех пор, пока все данные не будут переданы в буфер отправки.   -  person user207421    schedule 21.01.2015
comment
В дополнение к комментарию @EJP, перенесенному в буфер отправки локально, что не означает, что он был отправлен по сети (но тогда вы больше ничего не можете сделать ).   -  person Matthieu    schedule 13.04.2016


Ответы (3)


Код, который вы разместили, блокируется до тех пор, пока все данные не будут переданы в буфер отправки сокета, независимо от размера буфера отправки сокета. Ваши собственные эксперименты доказывают это. Вы не установили его на 131071, оставили на 8192, и все же было получено 131071 байт.

Вы имеете в виду, что одноранговый узел не получает более 131071 байт.

Это из-за размера буфера его сокета receive.

Чтобы установить размер буфера приема сокета больше 64 КБ, его необходимо установить до подключения сокета. В случае сервера это означает установку его в ServerSocket или ServerSocketChannel перед вызовом accept().

Однако ваша основная цель не реализуема. TCP — это протокол потока байтов. Он не обязан доставлять более одного байта за раз или ноль в неблокирующем режиме. Если вы хотите получить N байт, вам, как правило, придется зацикливаться.

person user207421    schedule 20.01.2015
comment
Не работает. Получатель — это ServerSocketChannel. В конструкторе я делаю так: uplink.socket().setReceiveBufferSize(2*1024*1024); но ничего - person Walter Bianchi; 21.01.2015
comment
И каков результат вызова getReceiveBufferSize() сразу после этого? - person user207421; 21.01.2015
comment
Результат 2097152 - person Walter Bianchi; 21.01.2015
comment
Я пытался зациклить, но не работает. Я не знаю как. Моя система находится в режиме блокировки - person Walter Bianchi; 21.01.2015
comment
Вы не умеете зацикливаться? - person user207421; 21.01.2015
comment
Я не знаю, как заставить его работать правильно. Я попытался зациклить запись и чтение с другой стороны, но безрезультатно. В частности, я думаю, что проблема для меня заключается в цикле, когда я читаю - person Walter Bianchi; 21.01.2015
comment
Поэтому опубликуйте текущий код цикла. Отредактируйте его в своем вопросе. - person user207421; 18.02.2015

В моем случае поставьте это

clientChannelUp.socket().setReceiveBufferSize(2*1024*1024);
clientChannelUp.socket().setSendBufferSize(2*1024*1024);

в accept() и connect(), и это работает.

person Eddie    schedule 25.09.2019

В итоге решил так:

передатчик

while(buf.hasRemaining()) {
    channel.write(buf);
}

получатель

int r = clientChannelUp.read(buffer);
while(r==131071) {
    r=clientChannelUp.read(buffer);
}
buffer.flip();
person Walter Bianchi    schedule 22.01.2015
comment
Это ничего не решает. Цикл записи блокируется, возможно, навсегда, а цикл чтения — просто полная ерунда. Он отбрасывает все данные до последнего частичного чтения. - person user207421; 18.02.2015
comment
Это работает в моем приложении. Почему цикл чтения отбрасывает все данные до последнего частичного чтения? Если это неправильно, скажите мне, как я должен сделать. - person Walter Bianchi; 18.02.2015
comment
Пожалуйста, люди, не делайте этого ... Вы хотя бы пытались увеличить размер буфера приема (clientChannelUp.socket().setReceiveBufferSize(xxx)), как @EJP указывал вам тоже (несколько раз ...)? Все что угодно лучше, чем жесткое кодирование эмпирически определенного значения. - person Matthieu; 13.04.2016