这两天优化端口扫描脚本,在获取HTTP页面内容时,发现requests.get hang住了(之前httplib不会)。
requests.get 提供了超时参数timeout,但在实际使用过程中,仍发现get请求可能被hang住。
原因在于非HTTP Server,response中一直没有出现换行符\n,导致_read_status()在获取状态码的时候就hang住了。
一个简单的解决方法,可以创建新的线程,示例代码参考如下,这部分代码是无法直接工作的:
def do_get_thread(url, ret): try: headers = { 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 ' '(KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25', 'Range': 'bytes=0-10240', 'Connection': 'Close'} ret.append(requests.get(url, headers=headers, timeout=(4, 30))) except: pass def get_http_title(ip, port, service, log_queue): if service.lower().find('https') >= 0 or service.lower().find('ssl') >= 0: service = 'https' else: service = 'http' url = '%s://%s:%s' % (service, ip, port) msg = 'Get http title %s' % url log_queue.put(msg) try: start_time = time.time() ret = [] t = threading.Thread(target=do_get_thread, args=(url, ret)) t.daemon = True t.start() while t.isAlive(): if time.time() - start_time > 31: log_queue.put('[get_http_title timed out] %s' % url) return {}, '' else: time.sleep(1.0) if not ret: return {}, '' resp = ret[0] headers = resp.headers m = re.search('<title>(.*?)</title>', resp.text, re.IGNORECASE) http_title = m.group(1).strip() if m else '' if http_title: http_title = decode_response_text(http_title) else: http_title = resp.text.replace('\n', ' ').strip()[0:200] return headers, http_title except requests.exceptions.RequestException, e: pass except Exception, e: log_queue.put('[get_http_title.exception] %s' % str(e)) return {}, ''
能给出具体的响应包么?
我这边用nc监听的话,然后不包含\n,超时依然有效
试试这个,应该能hang住:
http://s36.sq.pps.tv:9001
from requests import Request, Session
s = Session()
req = Request(‘GET’, “http://s36.sq.pps.tv:9001”)
prepped = req.prepare()
resp = s.send(prepped, timeout=5)
这样可以, 然后 catch 这个异常就可以.
—————————————————————————
ReadTimeout Traceback (most recent call last)
timeout需要大于30s,就可以复现了。
记得网络超时 分三种超时,还有一种是 一直推送的,导致无法关闭连接。
有python3的脚本吗