Я написал миниатюрный прокси-модуль в Python 3, чтобы просто сидеть между моим браузером и Интернетом. Моя цель - просто прокси трафика, идущего туда и обратно. Одно из действий программы - сохранять ответы сайта, которые я получаю, в локальном каталоге.
Все работает так, как я ожидаю, за исключением простого факта, что использование socket.recv()
в цикле, похоже, никогда не приведет к пустому объекту bytes
, подразумеваемому в примерах , приведенных в документах . Практически каждый пример в сети говорит о пустой строке, проходящей через сокет, когда сервер закрывает ее.
Я предполагаю, что что-то происходит через заголовок keep-alive, где удаленный сервер никогда не закрывает сокет, пока не будет достигнут собственный порог тайм-аута. Это правильно? Если да, то как мне узнать, когда закончена отправка полезной нагрузки? Наблюдение за тем, что полученные данные меньше моего объявленного размера порции, вообще не работает из-за того, как функционирует TCP.
Для демонстрации следующий код открывает сокет в файле изображения на веб-сервере Google. Я скопировал фактическую строку запроса из собственных запросов моего браузера. Выполнение кода (помните, Python 3!) Показывает, что двоичные данные изображения получены до завершения, но тогда код никогда не сможет выполнить оператор break
. Только когда сервер закрывает сокет (после 3 минут простоя) этот код фактически достигает команды print
в конце файла.
Как же можно обойти это? Моя цель - не изменять поведение запросов моего браузера - я не хочу устанавливать для заголовка keep-alive
значение false
или что-то безвкусное. Является ли ответ использовать некрасивые тайм-ауты (через socket.settimeout()
)? Кажется смешным, но я не знаю, что еще можно сделать.
Заранее спасибо.
import socket
remote_host = 'www.google.com'
remote_port = 80
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((remote_host, remote_port))
remote_socket.sendall(b'GET http://www.google.com/images/logos/ps_logo2a_cp.png HTTP/1.1\r\nHost: www.google.com\r\nCache-Control: max-age=0\r\nPragma: no-cache\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.794.0 Safari/535.1\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r\n\r\n')
content = b''
while True:
msg = remote_socket.recv(1024)
if not msg:
break
print(msg)
content += msg
print("DONE: %d" % len(content))