Обработка EOF в цикле чтения SOCKS на Python
Обрабатывайте EOF явно в цикле точного чтения SOCKS, вместо того чтобы считать закрытое соединение тайм-аутом, который никогда не наступает.
Цикл хочет получить восемь байт ответа SOCKS. Он получил три. Следующее чтение возвращает b'', цикл добавляет его, проверяет длину и снова пытается до бесконечности.
Это ошибка обработки EOF, а не медленный прокси, которому нужен более длительный тайм-аут. При обычном приёме через потоковый сокет пустая строка байтов означает, что партнёр отключился. Оставшиеся пять байт не придут по этому соединению.
Помощнику точного чтения нужны три разных исхода: накапливать непустые фрагменты, завершаться ошибкой при EOF до нужной длины и передавать тайм-аут или другую ошибку сокета. Эти случаи не должны сливаться в один общий цикл повторных попыток.
Задайте предполагаемый тайм-аут сокета перед операцией и читайте длины полей, указанные протоколом прокси. Один приём может вернуть только часть ответа. И наоборот, запрос большого фиксированного буфера не делает каждый адрес SOCKS такой длины.
Не исправляйте зависимость, вставляя старый фрагмент MSG_WAITALL в её исходный код и предполагая, что он покрывает EOF, сигналы и поведение платформы. Предпочитайте поддерживаемое исправление в сопровождаемой реализации или сознательно реализуйте контракт помощника, когда парсер — ваш код.
Сохраняйте, сколько байт ожидалось и было получено, не записывая полезные нагрузки учётных данных. «EOF после трёх из восьми байт ответа» объясняет сломанный обмен гораздо лучше, чем «прокси снова завис».