Одна вещь, которая могла бы помочь, это если бы вы продумали точно , что должна делать эта функция.То, что он на самом деле делает, вероятно, не то, что вы хотели, и имеет некоторые плохие функции.
Основные функции того, что он делает, что я заметил, это:
- Изменение некоторого глобального состояния
- Дождаться (до 1 миллисекунды), пока в буфере записи не будет свободного места
- Прервать, если буфер еще заполнен
- Отправить 1 или более байтов в сокет (игнорируя, сколько было отправлено)
- Если произошла ошибка (включая отправку, решившую, что она заблокирована, несмотря на более раннюю проверку), получите ее значение.В противном случае получите случайное значение ошибки
- Возможно, выведите что-то на экран в зависимости от полученного значения
- Верните 0 или 1, в зависимости от значения ошибки.
Комментарии к этим пунктам:
- Почему
write_flags
глобальный? - Вы действительно намеревались заблокировать эту функцию?
- Thisвероятно, все в порядке
- Конечно, вам небезразлично сколько данных было отправлено?
- Я не вижу ничего в документации, которая предполагает, что это будет ноль, если
send
преуспевает
Если вы выясните, каково было истинное намерение этой функции, вероятно, было бы намного легче гарантировать, что эта функция действительно выполняет это намерение.
При этом
У меня есть некоторые данные, которые мне нужно отправить на все эти потоковые сокеты
Что именно точно вам нужно?
Если вашнеобходимо, чтобы данные были отправлены перед продолжением, а затем с использованием неблокирующей записинеуместно *, поскольку вам все равно придется подождать, пока вы сможете записать данные.
Если вам нужно, чтобы данные отправлялись когда-нибудь в будущем, то в вашем решении отсутствует очень важныйкусок: вам нужно создать буфер для каждого сокета, который содержит данные, которые должны быть отправлены, а затем вам периодически нужно вызывать функцию, которая проверяет сокеты, чтобы попытаться написать все, что может.Если вы создаете новый поток для этой последней цели, это очень полезно для select
, поскольку вы можете создать этот новый поток, пока он не сможет что-то записать.Однако, если вы не создаете новый поток и просто периодически вызываете функцию из основного потока для проверки, вам не нужно беспокоиться.(просто напишите все, что можете, даже если это нулевые байты)
*: По крайней мере, это очень преждевременная оптимизация.Есть некоторые крайние случаи, когда вы могли бы немного повысить производительность, используя интеллектуальную неблокирующую запись, но если вы не понимаете, что это за пограничные записи и как бы помогли неблокирующие записи, то угадать это вряд липолучить хорошие результаты.
РЕДАКТИРОВАТЬ: как подразумевается в другом ответе, это то, что операционная система хороша в любом случае.Вместо того, чтобы пытаться написать собственный код для управления этим, если вы обнаружите, что буферы сокетов заполнены, то увеличьте системные буферы.И если они все еще заполняются, вам следует действительно серьезно подумать о том, что ваша программа должна блокироваться так или иначе, чтобы она перестала отправлять данные быстрее, чем другой конец можетсправиться.т.е. просто используйте обычную блокировку send
s для всех ваших данных.