为什么当客户端进程被杀死时,服务器close_wait可以被清除

时间:2019-07-15 01:30:05

标签: node.js http https tcp

关闭TCP套接字有4个步骤。

  

客户端关闭FIN_WAIT_1 FIN M =>服务器

     

客户端FIN_WAIT_2 <= ACK M +1个服务器CLOSE_WAIT

     

客户端TIME_WAIT <= FIN N服务器LAST_ACK

     

客户端ACK N +1 =>服务器已关闭

如果客户端进程在服务器发送响应之前被杀死,那么客户端是否由于已死而不能发送最后一个ACK?服务器不释放“ CLOSE_WAIT”吗?

server.js

// npm i sleep
const http = require('http');
const sleep = require('sleep').sleep;

const server = http.createServer(async (req, res) => {
  res.statusCode = 200;
  console.log('get a request');
  await sleep(30); // sleep 30s
  res.end('goodbye\n');
  console.log('finish a request');
});
server.listen(6000);

client.js

const http = require('http');
const net = require('net');

const options = {
  port: 6000,
  host: '127.0.0.1',
  method: 'GET'
  // path: ''
};
const req = http.request(options, res => {
  res.setEncoding('utf8');
  res.on('data', function(chunk) {
    console.log('Response: ' + chunk);
  });
});
req.on('error', e => {
  console.error(`request error: ${e.message}`);
});
req.end();

setTimeout(() => {
  process.exit(1);
}, 2000); 
~ netstat -tanv | grep 6000
tcp4       0      0  127.0.0.1.6000         127.0.0.1.57786        CLOSE_WAIT  408241 146988  40426      0 0x0122 0x00000104
tcp4       0      0  127.0.0.1.57786        127.0.0.1.6000         FIN_WAIT_2  408300 146988  40434      0 0x2131 0x00000100

我希望“ CLOSE_WAIT”在服务器上持续存在,因为它没有从客户端获得ACK,但是30秒钟后它将清除。

1 个答案:

答案 0 :(得分:1)

以下是RedHat对CLOSE_WAIT的描述:

  

CLOSE_WAIT-表示服务器已收到第一个FIN信号   来自客户端,并且连接正在关闭中。这表示   套接字正在等待应用程序执行close()。插座可以在   CLOSE_WAIT状态无限期,直到应用程序将其关闭。错误场景   就像文件描述符泄漏:服务器未在套接字上执行close()   导致堆积CLOSE_WAIT套接字。

这纯粹是服务器端的问题,无论客户端是否被杀死。 30秒后超时的原因是因为套接字在睡眠30秒时一直处于打开状态,因此允许发送响应(当然为时已晚)并关闭套接字。

这与Java vs节点无关,只是处理请求的设计决定。