0
votes

It has 4 steps on closing a TCP socket.

client close FIN_WAIT_1 FIN M => server

client FIN_WAIT_2 <= ACK M + 1 server CLOSE_WAIT

client TIME_WAIT <= FIN N server LAST_ACK

client ACK N + 1 => server CLOSED

If the client process had been killed before the server sends a response, whether the client can't send the last ACK because it had been dead? The server doesn't release '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

I expect the 'CLOSE_WAIT' is persisting on the server because it doesn't get ACK from the client, but it will be clear after the 30s.

1
I'm not sure your diagram is correct, but in any case the only way out of CLOSE_WAIT is for the server to either close the socket or receive a reset. I think you're confusing CLOSE_WAIT with TIME_WAIT. I can't make much sense out of your title.user207421
the client had been dead and it will not send a signal to the server. CLOSE_WAIT should reside on the server. TIME_WAIT is the client state. I have many nodejs servers communicating with JAVA servers though eureka, but there are many 'close_wait' on the nodejs servers. ( Java => nodejs => Java or DB) I think reproducing this issue, I guess JAVA timeout is shorter than nodejs server.It cause a large of close_wait on nodejs server.Miser
CLOSE_WAIT means the local applicaton hasn't closed the socket yet. It doesn't have anything to do with timeouts or ACKs. It is basically a socket leak in your code.user207421
Your state diagram lacks (Close) in two places compared to the original in RFC 793 #3.5. This is important information. It shows when the respective applications close the socket.user207421

1 Answers

1
votes

Here is a description of CLOSE_WAIT from RedHat:

CLOSE_WAIT - Indicates that the server has received the first FIN signal from the client and the connection is in the process of being closed. This means the socket is waiting for the application to execute close(). A socket can be in CLOSE_WAIT state indefinitely until the application closes it. Faulty scenarios would be like a file descriptor leak: server not executing close() on sockets leading to pile up of CLOSE_WAIT sockets.

This is purely a server side problem regardless of the client being killed or not. The reason you time out after 30 seconds is because the socket is being held open while you sleep for 30 seconds, then the response is allowed to send (too late of course) and close the socket.

This has nothing to do with Java vs node - just a design decision in handling the request.