Apache HTTPClient抛出java.net.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

我正在创建一个(行为良好的)web spider,我注意到一些服务器导致Apache HttpClient给我一个SocketException——具体来说:

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客户机上,而不会发生在其他方法上

额外的问题:我用这个系统做了大量的爬行。除了ApacheHTTP客户机之外,通常还有更好的Java类吗?我发现了许多问题(例如我必须在上面的代码中捕获的NullPointerException)。HTTPClient似乎对服务器通信非常挑剔——比我对爬虫更挑剔,因为爬虫不能在服务器不工作时就崩溃

谢谢大家

解决方案 老实说,我没有一个完美的解决方案,但它是有效的,所以这对我来说已经足够好了

正如下面oleg所指出的,Bixo已经创建了一个爬虫程序,它可以定制HttpClient,从而对服务器更加宽容。为了“绕过”问题而不是解决问题,我在这里使用了Bixo提供的SimpleHttpFetcher: (链接已删除-所以认为我是垃圾邮件发送者,所以你必须自己用谷歌搜索)

这个解决方案的缺点是Bixo有很多依赖项,所以这对每个人来说都不是一个好办法。但是,您始终可以通过他们对DefaultHttpClient的使用来了解他们是如何实例化它以使其工作的。我决定使用整个类,因为它可以为我处理一些事情,比如自动重定向跟踪(以及报告最终的目标url),这些都很有用

谢谢大家的帮助

编辑:TinyBixo 大家好。所以,我喜欢Bixo的工作方式,但不喜欢它有那么多依赖项(包括所有Hadoop)。因此,我创建了一个大大简化的Bixo,没有所有依赖项。如果您遇到上述问题,我建议您使用它(如果您想更新它,请随时发出请求!)


此处提供:

尝试使用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));