NodeJS - “套接字挂断”实际上是什么意思?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16995184/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
NodeJS - What does "socket hang up" actually mean?
提问by JVG
I'm building a web scraper with Node and Cheerio, and for a certain website I'm getting the following error (it only happens on this one website, no others that I try to scrape.
我正在用 Node 和 Cheerio 构建一个网络抓取工具,对于某个网站,我收到以下错误(它只发生在这个网站上,我没有尝试抓取其他网站。
It happens at a different location every time, so sometimes it's url xthat throws the error, other times url xis fine and it's a different url entirely:
它每次都发生在不同的位置,所以有时它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)
This is very tricky to debug, I don't really know where to start. To begin, what ISa socket hang up error? Is it a 404 error or similar? Or does it just mean that the server refused a connection?
这调试起来非常棘手,我真的不知道从哪里开始。首先,什么是套接字挂断错误?是 404 错误还是类似错误?还是仅仅意味着服务器拒绝了连接?
I can't find an explanation of this anywhere!
我在任何地方都找不到对此的解释!
EDIT: Here's a sample of code that is (sometimes) returning errors:
编辑:这是(有时)返回错误的代码示例:
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
});
}
There is no direct call to close the connection, but I'm using Node Requestwhich (as far as I can tell) uses http.getso this is not required, correct me if I'm wrong!
没有直接调用来关闭连接,但我正在使用Node Requestwhich(据我所知)使用,http.get所以这不是必需的,如果我错了,请纠正我!
EDIT 2: Here's an actual, in-use bit of code that is causing errors. prodURLand other variables are mostly jquery selectors that are defined earlier. This uses the asynclibrary for Node.
编辑 2:这是导致错误的实际使用中的代码位。prodURL和其他变量主要是之前定义的jquery选择器。这将使用asyncNode.js 库。
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);
}
]);
});
}
回答by Eye
There are two cases when socket hang upgets thrown:
socket hang up抛出时有两种情况:
When you are a client
当您是客户时
When you, as a client, send a request to a remote server, and receive no timely response. Your socket is ended which throws this error. You should catch this error and decide how to handle it: whether retry the request, queue it for later, etc.
当您作为客户端向远程服务器发送请求但未收到及时响应时。您的套接字已结束,这会引发此错误。您应该捕获此错误并决定如何处理它:是否重试请求、将其排队以备后用等。
When you are a server/proxy
当您是服务器/代理时
When you, as a server, perhaps a proxy server, receive a request from a client, then start acting upon it (or relay the request to the upstream server), and before you have prepared the response, the client decides to cancel/abort the request.
当您作为服务器(可能是代理服务器)收到来自客户端的请求,然后开始对其执行操作(或将请求中继到上游服务器),并且在您准备好响应之前,客户端决定取消/中止请求。
This stack trace shows what happens when a client cancels the request.
此堆栈跟踪显示客户端取消请求时会发生什么。
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)
Line http.js:1526:9points to the same socketCloseListenermentioned above by @Blender, particularly:
Linehttp.js:1526:9指向socketCloseListener@Blender 上面提到的相同内容,特别是:
// 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;
}
This is a typical case if the client is a user in the browser. The request to load some resource/page takes long, and users simply refresh the page. Such action causes the previous request to get aborted which on your server side throws this error.
如果客户端是浏览器中的用户,这是一个典型的情况。加载某些资源/页面的请求需要很长时间,用户只需刷新页面即可。此类操作会导致先前的请求中止,从而在您的服务器端引发此错误。
Since this error is caused by the wish of a client, they don't expect to receive any error message. So, no need to consider this error as critical. Just ignore it. This is encouraged by the fact that on such error the ressocket that your client listened to is, though still writable, destroyed.
由于此错误是由客户的意愿引起的,因此他们不希望收到任何错误消息。因此,无需将此错误视为关键。只是忽略它。令人鼓舞的是,在发生此类错误时res,您的客户端侦听的套接字虽然仍然可写,但会被销毁。
console.log(res.socket.destroyed); //true
So, no point to send anything, except explicitly closing the response object:
因此,除了明确关闭响应对象之外,没有必要发送任何内容:
res.end();
However, what you should dofor sure if you area proxy server which has already relayed the request to the upstream, is to abort your internal request to the upstream, indicating your lack of interest in the response, which in turn will tell the upstream server to, perhaps, stop an expensive operation.
但是,如果您是已经将请求中继到上游的代理服务器,您应该做的是中止对上游的内部请求,表明您对响应缺乏兴趣,这反过来会告诉上游服务器,也许,停止昂贵的操作。
回答by Blender
Take a look at the source:
看一下源码:
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;
}
}
The message is emitted when the server never sends a response.
当服务器从不发送响应时会发出该消息。
回答by silentorb
One case worth mentioning: when connecting from Node.js to Node.js using Express, I get "socket hang up" if I don't prefix the requested URL path with "/".
一个值得一提的案例:当使用 Express 从 Node.js 连接到 Node.js 时,如果我没有在请求的 URL 路径前加上“/”前缀,我会得到“套接字挂断”。
回答by Aekkawit Chanpen
I used require('http')to consume httpsservice and it showed "socket hang up".
我曾经require('http')使用过https服务,它显示“ socket hang up”。
Then I changed require('http')to require('https')instead, and it is working.
然后,我改变require('http')到require('https'),而是和它工作。
回答by Shiyas Cholamukhath
below is a simple example where I got the same error when I missed to add the commented code in below example. Uncommenting the code req.end()will resolve this issue.
下面是一个简单的例子,当我错过在下面的例子中添加注释代码时,我得到了同样的错误。取消注释代码req.end()将解决此问题。
var fs = require("fs");
var https = require("https");
var options = {
host: "en.wikipedia.org",
path: "/wiki/George_Washington",
port: 443,
method: "GET"
};
var req = https.request(options, function (res) {
console.log(res.statusCode);
});
// req.end();
回答by Sly
Expanding on Blender's answer, this happens in a number of situations. The most common ones I run into are:
扩展 Blender 的答案,这在许多情况下都会发生。我遇到的最常见的是:
- The server crashed.
- The server refused your connection, most likely blocked by
User-Agent.
- 服务器崩溃了。
- 服务器拒绝了您的连接,很可能被
User-Agent.
socketCloseListener, as outlined in Blender's answer, is not the only place that hangup errors are created.
socketCloseListener,如 Blender 的回答中所述,不是唯一产生挂断错误的地方。
For example, found here:
例如,在这里找到:
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();
}
You could try curlwith the headers and such that are being sent out from Node and see if you get a response there. If you don't get a response with curl, but you do get a response in your browser, then your User-Agentheader is most likely being blocked.
您可以尝试curl使用从 Node 发出的标头等,看看是否在那里得到响应。如果您没有收到响应curl,但您在浏览器中收到了响应,那么您的User-Agent标头很可能被阻止了。
回答by Milkncookiez
Another case worth mentioning (for Linux and OS X) is that if you use a library like httpsfor performing the requests, or if you pass https://...as a URL of the locally served instance, you will be using port 443which is a reserved private port and you might be ending up in Socket hang upor ECONNREFUSEDerrors.
另一个值得一提的情况(对于 Linux 和 OS X)是,如果您使用诸如https执行请求之类的库,或者如果您https://...作为本地服务实例的 URL传递,您将使用端口443,这是一个保留的专用端口,您可能会以Socket hang up或ECONNREFUSED错误告终。
Instead, use port 3000, f.e., and do an httprequest.
相反,使用 port 3000、 fe 并执行http请求。
回答by Marcin T.P. ?uczyński
I had the same problem while using Nanolibrary to connect to Couch DB. I tried to fine tune connection pooling with use of keepaliveagentlibrary and it kept failing with socket hang upmessage.
我在使用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
}
});
After some struggling I was able to nail the problem - as it came out it was very, very simple mistake. I was connecting to the database via HTTPS protocol, but I kept passing to my nano object a keepalive agent created as the examples for use of this library show (they rely on some defaults that use http).
经过一番挣扎,我终于解决了这个问题——结果出来了,这是一个非常非常简单的错误。我通过 HTTPS 协议连接到数据库,但我一直向我的 nano 对象传递一个 keepalive 代理,作为使用这个库显示的示例(它们依赖于一些使用 http 的默认值)。
One simple change to use HttpsAgentdid the trick:
使用HttpsAgent 的一个简单更改就成功了:
var KeepAliveAgent = require('agentkeepalive').HttpsAgent;
回答by Jeffrey Harmon
This caused me issues, as I was doing everything listed here, but was still getting errors thrown. It turns out that calling req.abort() actually throws an error, with a code of ECONNRESET, so you actually have to catch that in your error handler.
这给我带来了问题,因为我正在执行此处列出的所有操作,但仍然出现错误。事实证明,调用 req.abort() 实际上会抛出一个错误,带有 ECONNRESET 代码,因此您实际上必须在错误处理程序中捕获该错误。
req.on('error', function(err) {
if (err.code === "ECONNRESET") {
console.log("Timeout occurs");
return;
}
//handle normal errors
});
回答by Константин Ван
For requestmodule users
对于request模块用户
Timeouts
There are two main types of timeouts: connection timeoutsand read timeouts. A connect timeoutoccurs if the timeout is hit while your client is attempting to establish a connection to a remote machine (corresponding to the
connect()call on the socket). A read timeoutoccurs any time the server is too slow to send back a part of the response.
超时
有两种主要类型的超时:连接超时和读取超时。一个连接超时如果在您的客户端试图建立到远程计算机(对应于一个连接超时被击中发生
connect()在插座上的呼叫)。一个读超时发生时随时使用的服务器回送响应的一部分太慢。
Note that connection timeoutsemit an ETIMEDOUTerror, and read timeoutsemit an ECONNRESETerror.
请注意,连接超时会发出ETIMEDOUT错误,读取超时会发出ECONNRESET错误。

