Если я закрываю сокет сервера в цикле s.recv_into()
от клиента, я продолжаю получать 0 из recv_into()
бесконечно.
Да, как и ожидалось. Закрытое соединение обозначается 0, а не -1.
Как я понимаю, единственный способ узнать, что сокет закрыт, был не через сам механизм сокетов Python, а с помощью select / poll / etc.
Нет, это не правда. Простой вызов recv
в неблокирующем режиме сделает работу без использования какого-либо механизма выбора. В неблокирующем режиме состояние «еще нет данных» будет указано соответствующим исключением (обратите внимание, что вы должны проверить это исключение, это не единственный случай, когда recv
выбрасывает).
Однако это не означает, что одноранговый узел все еще жив (по умолчанию таймаут TCP составляет 15 минут AFAIK). Это не может быть надежно обнаружено. Лучшее, что вы можете сделать, это реализовать какой-либо протокол проверки связи по проводам.
Какой смысл не возвращать -1, когда сокет закрыт другой стороной?
Для системных вызовов (например, recv
) код возврата -1 (как правило) зарезервирован для ошибок. Однако Python переводит их в исключения (и поэтому AFAIK вы никогда не получите -1 в Python).
В любом случае 0 не является ошибкой. Это информация о том, что другая сторона закрыла соединение. Возможно, это вполне допустимая ситуация, и Python (или любой другой язык) не может этого знать.