对于node.js HTTP,res.end()如何保证套接字断开?

对于node.js HTTP,res.end()如何保证套接字断开?,http,node.js,httprequest,Http,Node.js,Httprequest,这是node.js的end实现: OutgoingMessage.prototype.end = function(data, encoding) { if (this.finished) { return false; } if (!this._header) { this._implicitHeader(); } if (data && !this._hasBody) { console.error('This type of r

这是node.js的end实现:

OutgoingMessage.prototype.end = function(data, encoding) {
  if (this.finished) {
    return false;
  }
  if (!this._header) {
    this._implicitHeader();
  }

  if (data && !this._hasBody) {
    console.error('This type of response MUST NOT have a body. ' +
                  'Ignoring data passed to end().');
    data = false;
  }

  var ret;

  var hot = this._headerSent === false &&
            typeof(data) === 'string' &&
            data.length > 0 &&
            this.output.length === 0 &&
            this.connection &&
            this.connection.writable &&
            this.connection._httpMessage === this;

  if (hot) {
    // Hot path. They're doing
    //   res.writeHead();
    //   res.end(blah);
    // HACKY.

    if (this.chunkedEncoding) {
      var l = Buffer.byteLength(data, encoding).toString(16);
      ret = this.connection.write(this._header + l + CRLF +
                                  data + '\r\n0\r\n' +
                                  this._trailer + '\r\n', encoding);
    } else {
      ret = this.connection.write(this._header + data, encoding);
    }
    this._headerSent = true;

  } else if (data) {
    // Normal body write.
    ret = this.write(data, encoding);
  }

  if (!hot) {
    if (this.chunkedEncoding) {
      ret = this._send('0\r\n' + this._trailer + '\r\n'); // Last chunk.
    } else {
      // Force a flush, HACK.
      ret = this._send('');
    }
  }

  this.finished = true;

  // There is the first message on the outgoing queue, and we've sent
  // everything to the socket.
  if (this.output.length === 0 && this.connection._httpMessage === this) {
    debug('outgoing message end.');
    this._finish();
  }

  return ret;
};
资料来源:

显然,只有当
output.length==0
时,连接才会“完成”

因此,如果仍然有数据等待写入,并且接收客户端出于某种原因在接收数据时不可靠,那么请求是否会结束

我也看到过这样的问题,当试图结束flash上传程序发出的http请求时,end无效。我最后做了以下几点,这确实有所帮助:

    res.end(failureJSON, 'utf8');
    req.once('end', function _destroyConn() {
        req.connection.destroy();
    });

看起来很粗俗。无论如何,
req.connection.destroy的这种行为是否需要保证从套接字断开连接?

不幸的是,
res.end()
没有直接“保证套接字断开连接”,因为它需要考虑HTTP保持活动。根据文档,
end
告诉服务器一切都已发送,响应已完成。是否立即断开连接完全取决于服务器对象

为了更具体地回答您的问题,重要的是响应需要发出
finish
事件。如果您看一下
\u finish()
的实现,它几乎只是发出事件

正如您所指出的,它并不总是直接调用
\u finish()
,但它确实设置了
this.finished=true
。当执行
\u flush()
时,它发送所有剩余数据,然后调用
\u finish()

这有点复杂,我不认为我可以在没有出错风险的情况下深入任何细节

至于有时不关闭的连接,您是否已检查是否正确配置了
保持活动状态
?如果HTTP连接默认设置为
keep alive
,则调用
end
不会关闭套接字


如果打印出的
res.shouldKeepAlive
,它将告诉您服务器是否正在尝试使用
保持活动状态
。如果要停止服务器执行此操作,请在请求处理程序开始时将其设置为
false

我不知道这是否有助于您为node 4.4+构建框架,但我已确认您可以在响应中发送
连接:close
头,以使node关闭连接

let res = getResponseSomehow()

res.statusCode = 408
res.setHeader("Connection", "close")
res.end()
您的销毁代码还可以使用以下调整:

// First we give node the time to close the connection
// We can give it 2 seconds
let socket = getSocketSomehow();
let timer = setTimeout(function() {
  socket.destroy();
}, 2000);

socket.on("close", function() {
  clearTimeout(timer);
});

我不太确定这是否是你想要的结束事件。我通常尝试使用一个库,远离
net
api,所以这只是一个猜测。

如果客户端声称连接保持活动状态,该怎么办?我认为不调用Flush命令是因为客户端正在阻止它(例如通过发送数据)
应覆盖任何客户端设置。因此,您的结论是,要正确结束连接,必须执行以下序列<代码>res.shouldKeepAlive=false;res.end()是否有任何具体方法强制关闭插座?@loganfsmyth如果您能回答我的最后一个问题,我将不胜感激。:)