const net = require('net');
// Create a server that demonstrates half-close
const server = net.createServer({ allowHalfOpen: true }, (socket) => {
console.log('Server: Client connected');
// Set encoding for the socket
socket.setEncoding('utf8');
// Track if we've received the FIN from client
let receivedFin = false;
// Handle data from client
socket.on('data', (data) => {
console.log(`Server received: ${data.trim()}`);
// After receiving data, send a response but don't end the connection
if (!receivedFin) {
console.log('Server: Sending response but keeping write side open');
socket.write('SERVER: Received your message. Send more or end your side.\n');
}
});
// Handle client ending their write side (sending FIN)
socket.on('end', () => {
receivedFin = true;
console.log('Server: Client ended their write side (FIN received)');
// We can still write to the client
console.log('Server: Sending final response');
socket.write('SERVER: Got your FIN. This is the final response.\n');
// Now we can fully close the connection
setTimeout(() => {
console.log('Server: Fully closing the connection');
socket.end();
}, 1000);
});
// Handle errors
socket.on('error', (err) => {
console.error('Server socket error:', err.message);
});
// Handle connection close
socket.on('close', (hadError) => {
console.log(`Server: Connection closed ${hadError ? 'with error' : 'normally'}`);
});
// Initial welcome message
socket.write('Welcome to the half-close demo server!\n');
socket.write('Send some data, then call end() on your side.\n');
});
// Start the server
const PORT = 3006;
const HOST = 'localhost';
server.listen(PORT, HOST, () => {
console.log(`Server running at ${HOST}:${PORT}`);
// Create a client to test half-close
const client = new net.Socket({ allowHalfOpen: true });
// Set encoding for the client
client.setEncoding('utf8');
// Track if we've received the FIN from server
let receivedFin = false;
// Connect to the server
client.connect(PORT, HOST, () => {
console.log('Client: Connected to server');
// Send initial data
console.log('Client: Sending initial data');
client.write('CLIENT: Hello from client\n');
// After a delay, send more data then half-close
setTimeout(() => {
console.log('Client: Sending more data then half-closing');
client.write('CLIENT: This is my last message\n');
// Half-close the connection (send FIN, but can still receive)
console.log('Client: Half-closing (ending write side)');
client.end('CLIENT: Ending my write side\n');
// We can still read from the server
console.log('Client: Write side closed, but can still receive data');
}, 1000);
});
// Handle data from server
let receivedData = '';
client.on('data', (data) => {
receivedData += data;
console.log('Client received data chunk');
// Check if we've received the final response
if (data.includes('final response')) {
console.log('Client: Received final response from server');
console.log('Full response:');
console.log(receivedData);
}
});
// Handle server ending their write side
client.on('end', () => {
receivedFin = true;
console.log('Client: Server ended their write side (FIN received)');
// Fully close the connection after a short delay
setTimeout(() => {
console.log('Client: Fully closing the connection');
client.destroy();
}, 1000);
});
// Handle connection close
client.on('close', (hadError) => {
console.log(`Client: Connection closed ${hadError ? 'with error' : 'normally'}`);
// Close the server
server.close();
});
// Handle errors
client.on('error', (err) => {
console.error('Client error:', err.message);
server.close();
});
});
// Handle server errors
server.on('error', (err) => {
console.error('Server error:', err.message);
});
// Close server after 30 seconds if not already closed
setTimeout(() => {
if (server.listening) {
console.log('Closing server due to timeout');
server.close();
}
}, 30000);