Понимание неблокирующего send

Рейтинг: 0Ответов: 1Опубликовано: 14.07.2023

В образовательных целях пишу http сервер без использования сторонних библиотек. В моей реализации все сокеты являются неблокирующими, и возникает вопрос, как реализовать отправку данных через send. Собственно сам вопрос заключается в поведении send при вызове на неблокирующем сокете.

Возвращаемое значение

Как сказано в MAN send(2)

On success, these calls return the number of bytes sent. On error, -1 is returned, and errno is set to indicate the error.

Не понимаю, что имеется ввиду, данные которые были реально отправлены, или данные, которые были помещены во внутренний буфер?

Данные не помещаются

В случае блокирующих сокетов всё понятно - в зависимости от возвращенного значения, вызываем send несколько раз, пока не будет передан весь буфер.
MAN send(2)

When the message does not fit into the send buffer of the socket, send() normally blocks, unless the socket has been placed in nonblocking I/O mode. In nonblocking mode it would fail with the error EAGAIN or EWOULDBLOCK in this case. The select(2) call may be used to determine when it is possible to send more data.

Как я понимаю, EAGAIN и EWOULDBLOCK имеют идентичный смысл и означают, что данные переданы во внутренний буфер не полностью и нужно с помощью select дождаться когда сокет будет writeable и отправить оставшиеся данные. Но тут возникает вопрос, как понять сколько байт было передано, если send вернет -1?

Ответы

▲ 0Принят

Не понимаю, что имеется ввиду, данные которые были реально отправлены, или данные, которые были помещены во внутренний буфер?

send возвращает число байтов, которые ядро записало в буфер очереди отправки. Даже блокирующий send не будет дожидаться от сетевой карты подтверждения отправки данных.

Но тут возникает вопрос, как понять сколько байт было передано, если send вернет -1?

Если есть свободное место в буферах, неблокирующий send запихнёт в них столько, сколько сможет, и вернёт число запихнутых байтов. send вернёт отрицательное число только в том случае, если окно на отправку заполнено целиком. В этом случае ваши данные останутся только вашими, ни один байт не будет скопирован в память ядра.