LINUX.ORG.RU

Отмена буферизации на сокете


0

0

Как отключить буферизацию на сокете так, чтобы в сеть передавались сообщения строго по одному, а не буфером из нескольких?

Такая потребность возникла в случае, когда передается поток данных, и этот поток нужно останавливать посылкой контрольного сообщения при использовании одного и того же канала и сокета в отличии от FTP. Из-за буферизации несколько сообщений успевают проскочить уже после посылки контрольного сообщения на запрет передачи. Попробывал out-of-band data (MSG_OOB) - не помогает, да это и понятно, буфер все равно разгребается и сообщения проскакивают после контрольного сообщения.

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

anonymous

вообще говоря, это невозможно. если вы про tcp, конечно.
TCP_NODELAY не поможет, вам нужен datagram протокол.

например, SOCK_SEQPACKET.

idle ★★★★★
()
Ответ на: комментарий от idle

> вообще говоря, это невозможно.

разумеется, вы можете реализовать свой протокола
обмена поверх tcp. например, не передавть следующий
пакет пока peer не подтвердит получение предыдущего.

idle ★★★★★
()
Ответ на: комментарий от idle

Речь идет о TCP/IP. Как известно, FTP может работать и через одно соединение в passive режиме, интересно как это реализовано.

Мне кажется, что проще просто отключить буфер, тогда send будет подвисать пока не передаст сообщение - то что надо.

Отключение алгоритма Нейгла не помогло, тут дело именно в буферизации.

anonymous
()
Ответ на: комментарий от anonymous

> Мне кажется, что проще просто отключить буфер, тогда send
> будет подвисать пока не передаст сообщение - то что надо.

не понимаю, о чем вы говорите, о каком буфере?

что бы вы не имели в виду, это работать не будет :)

idle ★★★★★
()
Ответ на: комментарий от idle

Под буфером я подразумеваю SO_SNDBUF: setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval));

Но это не срабатывает ...

anonymous
()
Ответ на: комментарий от anonymous

> Под буфером я подразумеваю SO_SNDBUF:
> Но это не срабатывает ...

разумеется, это не может работать.

tcp - reliable протокол, он _не_ может работать без
буферизации, мне и в голову не пришло, что вы надеетесь
выставить sk_sndbuf в 0.

подумайте хотя бы о том, что tcp протокол должен повторно
посылать данные, если не придет ack. как минимум это
означает, что эти данные нужно где-то сохранять.

только не надо думать, что у сокета действительно есть
один буфер, в котором все происходит. SO_SNDBUF означает
верхнюю границу для sk->sk_wmem_queued, а это есть сумма
skb->truesize.

idle ★★★★★
()

Можешь попытатся заюзать T/TCP

cvv ★★★★★
()
Ответ на: комментарий от anonymous

это можно былобы сделать только в случае если бы tcp не был таким быстрым и оптимизиравонным.

посланные данные должны храниться до тех пор пока их другая сторона не за-ackает. У тебя всегда должно быть место где эти данные можно временно хранить, если нет места то send может заблокировать и ждать пока появится место

если возникнет мемент когда tcp решит что данные надо переслать(не пришел ack за какое то время), то tcp может например склеить данные с вновь поступившими, тем самым уменьшив реальный трафико обмен(вместо двух пакетов посылается один) - это увеличит производительность tcp

поэтому по сути send() возвращает что данные посланы хотя на самом деле они еще не за-ackаны.

tcp позволяет тебе организовать достоверную доставку данных в достоверном порядке и делает это достаточно оптимизированно

весь остальной контроль(если требуется) за пересылкой данных должен лежать на более верхнем уровне .. то есть ты сам это контролируешь. Помни лишь что контроль доставки повех протокола с контролем доставки это неэфективно

lg ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.