举个栗子

好读书,不求甚解

Node.js socket hang up error

Kevalin's Avatar 2016-08-07

报socket hang up错误一般有2种可能,下面通过2个例子来说明:

客户端

客户端发送请求给远程服务端,没有及时收到服务端响应(默认超时时间为2分钟),这个时候socket就会结束,并抛出socekt hang up的错误信息,我们应该捕获这个错误并正确的处理它。

服务端/代理

客户端发送请求给服务器或者是代理服务器,服务器收到请求开始处理(如果是代理会将请求转发被后端真实的站点服务器),如果在服务器返回信息之前,客户端决定取消请求或者abort掉请求,这时候服务端也出现socekt hang up的报错,报错信息类似下面的例子,肯定会是从socketCloseListener这个函数抛出错误(下面会贴上源码)

1
2
3
4
5
6
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)

如果客户端是浏览器用户这种情况会经常发生,因为用户随时都有可能在服务器端没有返回前就进行了刷新页面的动作,这样的操作会导致前一个请求在服务器端抛出socket hang up的错误。

由于这个报错是客户端自己的意愿操作导致,并且用户也不希望收到任何的报错信息,所以不需要太刻意的处理这个错误信息,直接忽略即可。如果你是作为代理服务器,捕获到这样的报错最好是不要再将请求转发到后端去,直接处理掉即可。

涉及源码

注释也是写的很清楚的哦!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// _http_client.js
function createHangUpError() {
var error = new Error('socket hang up');
error.code = 'ECONNRESET';
return error;
}

// 上面的二种情况的错误处理
function socketCloseListener() {
var socket = this;
var req = socket._httpMessage;
debug('HTTP socket close');

// Pull through final chunk, if anything is buffered.
// the ondata function will handle it properly, and this
// is a no-op if no final chunk remains.
socket.read();

// NOTE: It's important to get parser here, because it could be freed by
// the `socketOnData`.
var parser = socket.parser;
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.socket._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.socket._hadError = true;
}

// Too bad. That output wasn't getting written.
// This is pretty terrible that it doesn't raise an error.
// Fixed better in v0.10
if (req.output)
req.output.length = 0;
if (req.outputEncodings)
req.outputEncodings.length = 0;

if (parser) {
parser.finish();
freeParser(parser, req, socket);
}
}

// 上面的第一种情况的错误处理
function socketOnEnd() {
var socket = this;
var req = this._httpMessage;
var parser = this.parser;

if (!req.res && !req.socket._hadError) {
// 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.socket._hadError = true;
}
if (parser) {
parser.finish();
freeParser(parser, req, socket);
}
socket.destroy();
}

本文作者 : Kevalin
本文使用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议
本文链接 : https://kevalin.github.io/2016/08/07/Node-js-socket-hang-up-error/