正 文:
在网上看到一位网友说:“我在timer中使用IdHTTP.get,头几个循环都是好的,但每次都是几分钟后就出现异常错误,显示"HTTP/1.1 400 Bad Request",我用try .... except abort; 虽然可以屏蔽错误,但循环执行也停止了.请问如何可以更正错误??? 或者屏蔽错误,而且程序依旧循环执行!”
飘易也遇到同样的问题。在线程内部实例化Tidhttp后,循环体中当访问的网址发生 “HTTP/1.1 400 Bad Request”时, Tidhttp直接抛出异常,这个异常导致整个循序体终止,如果此时还用 Tidhttp.disconnect 来关闭连接,则程序抛出 “application-defined-exception(code 0x0eedfade) at 0x7c812a5b ”错误,直接关闭程序。
其他的异常,如 【Socket Error # 10054 Connection reset by peer.】用try except 可以正常处理,只有 HTTP/1.1 400 Bad Request 这个错误无法处理。
解决方法:每次是用 idhttp 后释放,然后重新建立。如下:
try //开始获取源码
IdHttp1:=TIdHttp.Create(nil); //内部建立
IdHttp1.Request.UserAgent:='Mozilla/4.0 (compatible;)';
IdHttp1.ReadTimeout:=2000; //实际超时时间*3
IdHttp1.ConnectTimeout:=3000;
str:=IdHttp1.Get(url); //默认返回gbk编码的
IdHttp1.Disconnect;
IdHttp1.Free;
webs := str + UTF8Decode(str); //gbk的加上uft-8解码后的
except
on ex:exception do begin
webs := '';
IdHttp1.Free; //异常时,只能释放,不能 Disconnect
form.memo1.text :='【'+ ex.Message +'】'+#13#10+ form.memo1.text;
end;
end;
我在使用 idhttp 组件的过程中,还发现,如果循环中有过多的 调用该组件时,即使在释放idhttp后,依然占据了大量的系统端口号,用
netstat -ano 查看端口时, 如下
TCP 192.168.1.8:2700 58.221.35.134:80 TIME_WAIT 0
TCP 192.168.1.8:2702 174.139.74.212:80 TIME_WAIT 0
TCP 192.168.1.8:2704 58.64.163.120:80 TIME_WAIT 0
TCP 192.168.1.8:2706 174.139.74.212:80 TIME_WAIT 0
TCP 192.168.1.8:2708 174.139.74.211:80 TIME_WAIT 0
TCP 192.168.1.8:2710 58.64.163.120:80 TIME_WAIT 0
TCP 192.168.1.8:2712 113.105.153.158:80 TIME_WAIT 0
TCP 192.168.1.8:2714 58.221.35.134:80 TIME_WAIT 0
TCP 192.168.1.8:2716 58.64.163.120:80 TIME_WAIT 0
TCP 192.168.1.8:2718 116.252.185.197:80 TIME_WAIT 0
TCP 192.168.1.8:2720 58.221.31.233:80 TIME_WAIT 0
TCP 192.168.1.8:2722 111.68.8.227:80 TIME_WAIT 0
TCP 192.168.1.8:2724 116.252.185.140:80 TIME_WAIT 0
TCP 192.168.1.8:2726 58.64.163.120:80 TIME_WAIT 0
TCP 192.168.1.8:2736 58.64.163.120:80 TIME_WAIT 0
TCP 192.168.1.8:2740 58.64.163.120:80 TIME_WAIT 0
TCP 192.168.1.8:2746 65.19.157.234:80 TIME_WAIT 0
TCP 192.168.1.8:2750 58.64.163.120:80 TIME_WAIT 0
TCP 192.168.1.8:2760 98.126.67.20:80 TIME_WAIT 0
TCP 192.168.1.8:2762 58.221.35.134:80 TIME_WAIT 0
TCP通讯方式下,有众多的 TIME_WAIT 等待 close,当你的循环体内有足够多的网址需要抓取时,系统有限的端口将会被占用完,资源耗尽时,电脑将无法访问网络。无论用idhttp1.disconnect,idhttp1.destroy,idhttp1.free 都无法立即关闭这样的连接。TCP通讯方式下,客户端先关闭连接,先停止发送数据,则客户端先进入 TIME_WAIT,微软给的说法是 TIME_WAIT 等待3分钟后会自动 close。但飘易的担心是如 打开的速度 高于 关闭的速度时,系统的端口一定会被用完。即idhttp连续N次的GET or POST后,idhttp将自动停止工作。