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.
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.
User contributions licensed under CC BY-SA 3.0