NodeJS – “套接字挂断”究竟是什么意思?

我正在build立一个networking刮板与节点和Cheerio,和一个特定的网站,我得到以下错误(它只发生在这一个网站,没有其他人,我试图刮。

它发生在每一个不同的位置,所以有时它的url x引发错误,其他时间url x是好的,这是一个完全不同的url:

  Error!: Error: socket hang up using [insert random URL, it's different every time] Error: socket hang up at createHangUpError (http.js:1445:15) at Socket.socketOnEnd [as onend] (http.js:1541:23) at Socket.g (events.js:175:14) at Socket.EventEmitter.emit (events.js:117:20) at _stream_readable.js:910:16 at process._tickCallback (node.js:415:13) 

这是非常棘手的debugging,我真的不知道从哪里开始。 首先,什么套接字挂断错误? 这是404错误还是类似的? 或者这是否意味着服务器拒绝连接?

我找不到任何地方的解释!

编辑:这是(有时)返回错误的代码示例:

 function scrapeNexts(url, oncomplete) { request(url, function(err, resp, body) { if (err) { console.log("Uh-oh, ScrapeNexts Error!: " + err + " using " + url); errors.nexts.push(url); } $ = cheerio.load(body); // do stuff with the '$' cheerio content here }); } 

没有直接调用来closures连接,但我使用Node Request (使用http.get所以这不是必需的,纠正我,如果我错了!

编辑2:这是一个实际的,正在使用的代码是造成错误的位。 prodURL和其他variables大多是前面定义的jqueryselect器。 这使用Node的async库。

 function scrapeNexts(url, oncomplete) { request(url, function (err, resp, body) { if (err) { console.log("Uh-oh, ScrapeNexts Error!: " + err + " using " + url); errors.nexts.push(url); } async.series([ function (callback) { $ = cheerio.load(body); callback(); }, function (callback) { $(prodURL).each(function () { var theHref = $(this).attr('href'); urls.push(baseURL + theHref); }); var next = $(next_select).first().attr('href'); oncomplete(next); } ]); }); } 

socket hang up时出现两种情况:

当你是一个客户

当你作为一个客户向远程服务器发送一个请求,并没有得到及时的回应。 你的套接字结束了,抛出这个错误。 您应该捕获这个错误并决定如何处理它:是否重试请求,排队等等等等。

当你是一个服务器/代理

当你作为一个服务器,也许是一个代理服务器,接收到来自客户端的请求,然后开始对其执行操作(或者将请求转发给上游服务器),并且在准备好响应之前,客户端决定取消/终止请求。

此堆栈跟踪显示当客户端取消请求时发生的情况。

 Trace: { [Error: socket hang up] code: 'ECONNRESET' } at ClientRequest.proxyError (your_server_code_error_handler.js:137:15) at ClientRequest.emit (events.js:117:20) at Socket.socketCloseListener (http.js:1526:9) at Socket.emit (events.js:95:17) at TCP.close (net.js:465:12) 

http.js:1526:9指向上面由@Blender提到的相同的socketCloseListener,特别是:

 // This socket error fired before we started to // receive a response. The error needs to // fire on the request. req.emit('error', createHangUpError()); ... function createHangUpError() { var error = new Error('socket hang up'); error.code = 'ECONNRESET'; return error; } 

如果客户端是浏览器中的用户,则这是典型的情况。 加载一些资源/页面的请求需要很长时间,用户只需刷新页面。 这样的行为导致以前的请求被中止,在你的服务器端抛出这个错误。

由于这个错误是由客户的期望造成的,所以他们不希望收到任何错误信息。 所以,不需要把这个错误当作关键。 只要忽略它。 这是鼓励的事实,在这样的错误你的客户端收听的res套接字虽然仍然可写,销毁。

 console.log(res.socket.destroyed); //true 

所以,除了明确地closures响应对象之外,没有意义发送任何东西:

 res.end(); 

然而,如果你一个代理服务器,它已经把请求传递给上游,你应该做的是放弃你对上游的内部请求,表明你对响应缺乏兴趣,这反过来会告诉上游服务器,也许,停止昂贵的操作。

看看源代码 :

 function socketCloseListener() { var socket = this; var parser = socket.parser; var req = socket._httpMessage; debug('HTTP socket close'); req.emit('close'); if (req.res && req.res.readable) { // Socket closed before we emitted 'end' below. req.res.emit('aborted'); var res = req.res; res.on('end', function() { res.emit('close'); }); res.push(null); } else if (!req.res && !req._hadError) { // This socket error fired before we started to // receive a response. The error needs to // fire on the request. req.emit('error', createHangUpError()); req._hadError = true; } } 

消息在服务器从不发送响应时发出。

值得一提的是:当使用Express从Node.js连接到Node.js时,如果我不用“/”前缀所请求的URLpath,我会得到“套接字挂起”的问题。

根据Blender的回答,这在很多情况下都会发生。 我遇到的最常见的是:

  1. 服务器崩溃了。
  2. 服务器拒绝您的连接,很可能被User-Agent拦截。

socketCloseListener Blender的回答所述, socketCloseListener并不是创build挂断错误的唯一地方。

例如,在这里find:

 function socketOnEnd() { var socket = this; var req = this._httpMessage; var parser = this.parser; if (!req.res) { // If we don't have a response then we know that the socket // ended prematurely and we need to emit an error on the request. req.emit('error', createHangUpError()); req._hadError = true; } if (parser) { parser.finish(); freeParser(parser, req); } socket.destroy(); } 

你可以尝试使用头部curl ,并从节点发出,看看你是否得到了答复。 如果你没有得到curl的回应,但是你的浏览器得到了回应,那么你的User-Agent头很可能被阻止了。

另一个值得一提的情况(对于Linux和OS X)是,如果您使用像https这样的库执行请求,或者如果您通过https://...作为本地服务实例的URL,则将使用端口443这是一个保留的私有端口,你可能会在Socket hang upECONNREFUSED错误结束。

相反,使用端口3000 ,fe,并做一个http请求。

在使用Nano库连接到Couch DB时,我遇到了同样的问题。 我试图微调连接池使用keepaliveagent库,并保持与套接字挂断消息失败。

 var KeepAliveAgent = require('agentkeepalive'); var myagent = new KeepAliveAgent({ maxSockets: 10, maxKeepAliveRequests: 0, maxKeepAliveTime: 240000 }); nano = new Nano({ url : uri, requestDefaults : { agent : myagent } }); 

经过一番苦苦挣扎之后,我才发现这个问题非常非常简单。 我通过HTTPS协议连接到数据库,但是我不停地向我的nano对象传递一个keepalive代理,作为使用这个库展示的示例(它们依赖于使用http的一些默认值)。

使用HttpsAgent的一个简单的改变做了诀窍:

 var KeepAliveAgent = require('agentkeepalive').HttpsAgent; 

我的情况是,我使用require('http')来使用https服务 ,并显示“ Socked挂断 ”。

然后我使用require('https')来代替,并且它正在工作。 希望这个帮助。

在请求到某个服务器时,我遇到了同样的问题。 在我的情况下,请求选项中的标头中设置任何值到User-Agent帮助我。

 const httpRequestOptions = { hostname: 'site.address.com', headers: { 'User-Agent': 'Chrome/59.0.3071.115' } }; 

这不是一般情况,取决于服务器设置。

在我的情况,这是因为应用程序/ JSON响应格式不正确(包含堆栈跟踪)。 该响应从未发送到服务器。 debugging非常棘手,因为没有日志。 这个线程帮助我了解发生了什么。

如果你正在使用node-http-proxy,请注意这个问题,这将导致套接字挂起错误: https : //github.com/nodejitsu/node-http-proxy/issues/180 。

为了解决这个问题,在这个链接中,只需在express.bodyParser()之前的快速路由中声明API路由(用于代理)。

进入这个问题昨天运行我的Web应用程序和node.js服务器通过IntelliJ IDEA 2016.3.6。 我所要做的只是在我的Chrome浏览器中清除我的Cookie和caching。

我做了networking(节点)和Android开发,并且一起打开了Android Studio设备模拟器和coker,两者都使用8601端口,抱怨socket hang up错误,closures了Android Studio设备模拟器,在节点端运行良好。 不要一起使用Android Studio设备模拟器和docker。