Есть серверное приложение, работающее с неблокирующими сокетами. Заряжаем select на готовность данных для чтения, она будет успешна даже в том случае, если соеденение завершено. Дальше, вызываем recv, который после принятия всей порции данных, опять же в цикле после select, возвращает ноль, но соеденение никто не закрывал! (при этом теряется весь смысл вызова select, в данном случае) Клиент просто висит в ожидании. 1. Может быть, утверждение "If the connection has been gracefully closed, the return value is zero" верно только для блокирующих сокетов? 2. Почему recv возвращает 0? 3. Как в моем случае понять, что соеденение действительно завершилось? С уважением.
recv() возвращает SOCKET_ERROR, ноль или размер данных в байтах. Для blocking sockets последующий вызов просто блокирует поток, для non blocking получишь назад ошибку ...WOULDBLOCK. Обычно используются blocking socket + select() или non blocking + overlapped IO (completion ports). В первом случае ты просто вызываешь send() - пусть от будет blocking, но не должен вызывать recv() пока не пулучишь сигнал от select().
Это неправильно утверждение. recv вернет 0 в том случае, если удаленный хост закрыл свою половину соединения ( помним, что TCP дуплексный протокол; он может работать в полузакрытом состоянии, когда данные передаются только в одну сторону ). "has been gracefully closed" - это значит, что соединение полностью закрыто, т.е обе стороны вызвали shutdown ( s, SD_SEND ), что приводит к послыке FIN пакета. Потому что ваш хост получил FIN пакет от другой стороны, можете убедиться в этом с помощью сниффера ( это 100% так, если конечно это не баг в вашем коде ). Противоположенная сторона закрыла свою половину соединения и теперь ждет этого от вас. В принципе, вы можете продолжать передавать данные, но обычно протоколы не работают в с полузакрытыми соединениями, поэтому разумно в данной ситуации вызвать: shutdown ( s, SD_SEND ); closesocket( s ); Вызов shutdown можно опустить, если вы не трогали опцию SO_LINGER