Я знаю, что это старая ветка, но для тех, кто наткнулся на это через поисковик, я отвечу на вопрос, так как на самом деле выше не было ответа.
Перед тем, как начать, преодолеть зависание системного вызова - вы не можете взаимодействовать с сетевыми стеками на основе ядра (* nix) без включения и выключения пространства ядра. Ваша цель должна состоять в том, чтобы понять особенности стека, чтобы вы могли извлечь максимальную пользу из своей системы.
Как определить, заполнен ли буфер сокета чтения
На эту часть ответили - нет, потому что это не то, как вы должны думать.
Если отправитель (плохо) фрагментирует свои кадры TCP (обычно из-за отсутствия буферизации маршалированных данных на выходе и отключения алгоритма Nagle с помощью TCP_NDELAY), ваша идея уменьшить количество системных вызовов, которые вы делаете, является хорошей идея. Подход, который вы должны использовать, включает установку «низкого водяного знака» для чтения. Сначала вы устанавливаете разумный размер буфера приема, устанавливая SO_RCVBUF с помощью setsockopt (). Затем прочитайте реальный размер буфера чтения с помощью getsockopt (), так как вы можете не получить то, что просили :) К сожалению, не все реализации позволяют вам снова читать SO_RCVBUF, поэтому ваш пробег может отличаться. Затем решите, сколько данных вы хотите представить для чтения, прежде чем захотите их прочитать. Установите SO_RCVLOWAT с этим размером, используя setsockopt (). Теперь файловый дескриптор сокета будет выбирать только для чтения, когда есть по крайней мере того количества данных, которые читаются для чтения.
или буфер сокета записи пуст?
Это интересный вопрос, поскольку мне нужно было сделать это недавно, чтобы убедиться, что каждый мой ADB MODBUS / TCP занял свои собственные кадры TCP, что требуется спецификацией MODBUS (@steve: управление фрагментацией - один раз, когда вы делаете нужно знать, когда буфер отправки пуст!). Что касается оригинального постера, я очень сомневаюсь, что он действительно этого хочет, и верю, что ему будет гораздо лучше знать размер буфера отправки до его запуска и периодически проверять объем данных в буфере отправки во время отправки, используя методы, уже описанные. Это позволит получить более детальную информацию о пропорции используемого буфера отправки, которую можно было бы использовать для более плавного регулирования производства.
Для тех, кто все еще интересуется, как (асинхронно) определять, когда буфер отправки пуст (если вы уверены, что действительно то, что вы хотите), ответ прост - вы устанавливаете низкий уровень отправки. водяной знак (SO_SNDLOWAT) равен размеру буфера отправки. Таким образом, дескриптор файла сокета будет выбираться как доступный для записи только тогда, когда буфер отправки пуст.
Не случайно мои ответы на ваши вопросы вращаются вокруг использования select ().
Практически во всех случаях (и я понимаю, что сейчас я направляюсь на религиозную территорию!) Приложения, которым необходимо перемещать большое количество данных (внутри и между хостами), лучше всего структурировать как однопоточные конечные автоматы, используя маски выбора и цикл обработки, основанный на pselect (). В наши дни некоторые ОС (Linux, чтобы назвать одну) даже позволяют вам управлять обработкой сигналов, используя выбор файловых дескрипторов. Какая роскошь - когда я был мальчиком ...:)
Peter