Экспериментально обнаружил, что если вызвать sendto() на UDP-сокете 100500 раз подряд с маленькими сообщениями, то все вызовы вернут успех, но получателю приедет лишь малая доля отправленных сообщений.
For UDP sockets, there are no send buffers, so send() and sendto() never return EWOULDBLOCK
Packets are just silently dropped when a device queue overflows.
Получается, что в случае UDP-сокета, sendto() пишет сразу в буфер адаптера.
Я не стану задавать риторический вопрос, что мешало этим чертям проверять переполнение буфера адаптера и честно возвращать EWOULDBLOCK – чтобы отправитель мог сразу регулировать плотность трафика, а не через ожидание отсутствия подтверждения от получателя по таймауту (в результате чего у отправителя ВСЕГДА устаревшие данные о пропускной способности канала).
Мне интересно более практичное: если UDP-сокет никогда не возвращает EWOULDBLOCK (т.е. не проверяет переполнение буфера адаптера), есть ли смысл добавлять его во writeSet для select(), и как он себя в этом случае поведёт (ведь для срабатывания writeSet таки-нужно проверять наличие свободного места в буфере адаптера)?
Или же тупо писать в него безо всяких select(&writeSet)? Даже если writeSet сработает корректно, один хрен невозможно узнать, сколько можно записать и когда нужно остановиться.