Работает ли recv(...) таким образом?
Я устанавливаю таймаут для сокета, используя SO_RCVTIMEO
до 10 секунд. Этот вопрос относится к потоковому сокету (TCP). Когда я звоню recv(...)
из того, что я могу почерпнуть из справочных страниц, вот что я ожидаю:
- Если удаленное соединение закрывает соединение, оно немедленно возвращает 0 независимо от времени ожидания.
- Если время ожидания истекло и данные не были получены, то мы получаем -1 и возвращаемое
errno
изEAGAIN
или жеEWOULDBLOCK
, - Если в сокете возникает ошибка, она сразу возвращается с -1, а затем
errno
настроен правильно. - Если данные становятся доступными, сокет ждет, пока не истечет время ожидания, прежде чем вернуться. На этот раз он вернется через 10 секунд с общим количеством полученных байтов.
Это правильное поведение? Я просто хочу убедиться, что я правильно понимаю документы.
Спасибо! Brett
2 ответа
- Правильный.
- Есть две разные спецификации (к сожалению, я не могу проверить в настоящее время)
2,1ETIMEOUT
будет возвращен. (EAGAIN
или жеEWOULDBLOCK
возвращаются на неблокирующих сокетах, если данные сразу не доступны.) http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html
2,2EAGAIN
или жеEWOULDBLOCK
будет возвращено для обеих возможностей, упомянутых в 2.1 http://man7.org/linux/man-pages/man2/recvmsg.2.html - Правильный.
- Если был прочитан хотя бы 1 байт, сокет может вернуться в любое время, даже если будет прочитано меньше, тогда сообщается, и время ожидания еще не истекло.
Довольно много.
Есть одна оговорка: если вы установите MSG_WAITALL
По крайней мере одна реализация (FreeBSD) запускает таймер заново каждый раз, когда поступают некоторые данные. Например, если вы попросите recv
8192 байта и один байт прибывает, таймер сбрасывается. Если в течение 10 секунд поступит другой байт, таймер снова сбрасывается. Так что, если байты текут один раз в 5 секунд, вы будете ждать (8191 * 5) = 40955 секунд = более чем за 11 часов до recv
наконец возвращает 8192. (Если до EOF поступает недостаточно байтов, recv
не удается с EAGAIN
.)
Документация подразумевает (по крайней мере для меня), что это произошло даже без MSG_WAITALL
, но тестирование показывает, что это предостережение относится только к MSG_WAITALL
дело.