Обзор
Я использую urlopen из пакета Python 2.7.1 urllib2 для выполнения HTTP POST с компьютера под управлением Windows XP на удаленный веб-сервер Apache (например, встроенный общий доступ к Интернету в Mac OS X)).Отправленные данные содержат некоторый идентификатор, данные и контрольную сумму, если все данные отправлены, сервер отвечает подтверждением.Контрольная сумма в данных может использоваться, чтобы проверить, все ли прибыло в порядке.
Проблема
Обычно это работает отлично, однако иногда интернет-соединение плохое, часто потому, что клиент, отправляющийданные используют Wi-Fi или 3G-соединение.Это приводит к потере интернет-соединения в течение некоторого произвольного количества времени.urlopen содержит опцию тайм-аута, чтобы убедиться, что это не блокирует вашу программу и может продолжаться.
Это то, что я хочу, но проблема в том, что urlopen не мешает сокету продолжать отправлять любые данныеэто все еще должно было послать, когда истекло время ожидания.Я проверил это (с помощью кода, который я покажу ниже), пытаясь отправить большой объем данных на свой ноутбук, я видел бы сетевую активность на обоих шоу активности, затем я бы остановил беспроводную связь на ноутбуке, подождалпока не истечет время ожидания функции, а затем снова включите беспроводную связь, и передача данных продолжится, но программа больше не будет прослушивать ответы.Я даже пытался выйти из интерпретатора Python, и он все равно отправлял бы данные, поэтому управление им как-то передается Windows.
Причины
Тайм-аут (насколько я понимаю) работает следующим образом: Он проверяет «время ожидания простоя»
( [Python-Dev] Добавление тайм-аута сокета к urllib2 )
Если вы установите тайм-аут на 3, откроется соединение, запуститесчетчик, затем попытайтесь отправить данные и дождаться ответа, если в какой-то момент перед получением ответа таймер истекает, вызывается исключение тайм-аута.Обратите внимание, что отправка данных, по-видимому, не считается «активностью» в отношении таймера тайм-аута.
( urllib2 истекает, но не закрывает сокетное соединение )
( Закрыть соединение urllib2 )
Очевидно, где-то указано, что когда сокет закрыт / разыменован / собран мусор, он вызывает свою функцию 'close', которая ожидает отправки всех данных перед закрытиемразъем.Однако есть также функция отключения, которая должна немедленно останавливать сокет, предотвращая дальнейшую отправку данных.
( socket.shutdown против socket.close )
(http://docs.python.org/library/socket.html#socket.socket.close)
Что я хочу
Я хочу, чтобы при истечении времени ожидания соединение было «отключено».В противном случае мой клиент не сможет определить, были ли данные получены правильно или нет, и он может попытаться отправить их снова.Я предпочел бы просто разорвать соединение и повторить попытку позже, зная, что данные (вероятно) не были успешно отправлены (сервер может распознать это, если контрольная сумма не совпадает).
Вот часть кодачто я использовал для проверки этого.Попробовать .. кроме частей еще не работают, как я ожидал, любая помощь там также приветствуется.Как я уже говорил, я хочу, чтобы программа отключила сокет, как только возникнет исключение тайм-аута (или любого другого).
from urllib import urlencode
from urllib2 import urlopen, HTTPError, URLError
import socket
import sys
class Uploader:
def __init__(self):
self.URL = "http://.../"
self.data = urlencode({'fakerange':range(0,2000000,1)})
print "Data Generated"
def upload(self):
try:
f = urlopen(self.URL, self.data, timeout=10)
returncode = f.read()
except (URLError, HTTPError), msg:
returncode = str(msg)
except socket.error:
returncode = "Socket Timeout!"
else:
returncode = 'Im here'
def main():
upobj = Uploader()
returncode = upobj.upload()
if returncode == '100':
print "Success!"
else:
print "Maybe a Fail"
print returncode
print "The End"
if __name__ == '__main__':
main()