Apache HTTPClient抛出java.net.SocketException:许多域的连接重置
我正在创建一个(行为良好的)web spider,我注意到一些服务器导致Apache HttpClient给我一个SocketException——具体来说:Apache HTTPClient抛出java.net.SocketException:许多域的连接重置,java,apache,sockets,web-crawler,httpclient,Java,Apache,Sockets,Web Crawler,Httpclient,我正在创建一个(行为良好的)web spider,我注意到一些服务器导致Apache HttpClient给我一个SocketException——具体来说: java.net.SocketException: Connection reset 导致这种情况的代码是: // Execute the request HttpResponse response; try { response = httpclient.execute(httpget); //httpclient is o
java.net.SocketException: Connection reset
导致这种情况的代码是:
// Execute the request
HttpResponse response;
try {
response = httpclient.execute(httpget); //httpclient is of type HttpClient
} catch (NullPointerException e) {
return;//deep down in apache http sometimes throws a null pointer...
}
对于大多数服务器来说,这很好。但对其他人来说,它立即引发了一个SocketException
导致立即SocketException的站点示例:
效果很好(大多数网站也是如此):
现在,正如您所看到的,www.bhphotovideo.com在web浏览器中加载良好。当我不使用Apache的HTTP客户端时,它也可以正常加载。(代码如下:)
那么,为什么我不直接使用这个代码呢?Apache的HTTP客户机中有一些关键特性我需要使用
有人知道是什么原因导致某些服务器出现此异常吗
迄今为止的研究:
- 问题发生在我的本地Mac dev计算机和AWS EC2实例上,所以它不是本地防火墙
- 这个错误似乎不是由远程机器引起的,因为异常没有说“由对等机引起”
- 这个堆栈溢出似乎是相关的,但答案并没有说明为什么这只会发生在ApacheHTTP客户机上,而不会发生在其他方法上
此处提供:尝试使用wireshark获取网络跟踪,并使用HTTPClient的log4j日志记录来增强这一点。这将首先显示重置连接的原因,以回答您的问题: 连接重置是由服务器端的问题引起的。服务器很可能无法解析请求,或者无法处理请求,因此在没有返回有效响应的情况下断开了连接。HttpClient生成的HTTP请求中可能有某种东西导致服务器端逻辑失败,可能是由于服务器端错误。仅仅因为错误消息没有说“by peer”,并不意味着连接重置发生在客户端 几句话: (1) 一些流行的网络爬虫程序(如bixo)使用HttpClient时没有出现重大问题,但其中大部分都不得不调整HttpClient的行为,使其对常见的HTTP协议违规行为更加宽容。默认情况下,HttpClient对HTTP协议的遵从性要求相当严格 (2) 您为什么不向HttpClient项目报告NPE问题或您遇到的任何其他问题?有时会有所帮助:
client.getParams().setParameter("http.socket.timeout", new Integer(0));
client.getParams().setParameter("http.connection.stalecheck", new Boolean(true));
第一种方法将套接字超时设置为无限。您是如何实例化HttpClient的?如果只是偶尔发生这种情况,则可能需要在完成响应后关闭响应,以确保返回所有资源。这可能会导致连接泄漏,最终导致像您遇到的问题一样的问题。您好,谢谢您将我指给Bixo。我在主要问题区补充了我是如何解决这个问题的。至于不报告NPE——你说得对,我下次捕获堆栈跟踪时会这样做!将套接字超时设置为无限大不是导致线程卡住的方法吗?我不确定这是否可取。
SimpleHttpFetcher fetch = new SimpleHttpFetcher(new UserAgent("botname","contact@yourcompany.com","ENTER URL"));
try {
FetchedResult result = fetch.fetch("ENTER URL");
System.out.println(new String(result.getContent()));
} catch (BaseFetchException e) {
e.printStackTrace();
}
client.getParams().setParameter("http.socket.timeout", new Integer(0));
client.getParams().setParameter("http.connection.stalecheck", new Boolean(true));