You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js Net Socket连接未正常关闭,后续连接无响应问题求助

Node.js TCP Socket连接未正常关闭导致后续请求无响应问题

编写Node.js TCP服务器时遇到问题:客户端或服务器未真正关闭Socket连接,导致服务器对后续连接无响应。客户端发送第二次请求后挂起,服务器未进入socket.on('data' ...)监听器。

服务端代码(server.js)

const net = require('net');
const serverAddress = '127.0.0.1'; // Replace with the actual server address
const serverPort = 3000; // Replace with the actual server port

const server = net.createServer(socket => {
    socket.on('data', data => {
        console.log('Received request: ', data.toString())
        socket.write('Hi, this is server response');
    });
    socket.on('close', () => {
        socket.end();
        socket.destroy();
        console.log('Connection closed');
    });
    socket.on('end', () => {
        console.log('Connection end');
        socket.end();
    });
    socket.on('error', error => {
        console.error('Socket error:', error);
    });
});

server.listen(serverPort, serverAddress, () => {
    console.log(`Server listening on ${serverAddress}:${serverPort}`);
});

客户端代码(client.js)

const net = require('net');
const serverAddress = '127.0.0.1'; // Replace with the actual server address
const serverPort = 3000; // Replace with the actual server port

const client = net.createConnection(serverPort, serverAddress, () => {
    console.log('Connected to the server');
    let msg = 'First request';
    client.write(msg);
    console.log("Sent2 to server:", msg)

    client.on('data',  data => {
        console.log('Server response:', data.toString());
        client.end();
    });
    client.on('close', () => {
        console.log('Connection closed');
    });
    client.on('end', async () => {
        console.log('Connection end');
        setTimeout(runSecondConnection, 3000);
    });
});

function runSecondConnection() {
    let client2 = net.createConnection(serverPort, serverAddress, () => {
        console.log('Connected2 to the server');
        let msg = 'Second request';
        client.write(msg);
        console.log("Sent2 to server:", msg)
    })

    client2.on('data', data => {
        console.log('Server2 response:', data.toString());
        client.end();
    });
    client2.on('close', () => {
        console.log('Connection2 closed');
    });
    client2.on('end', () => {
        console.log('Connection2 end');
    });

}

实际运行结果

服务器输出

Received request:  First request
Connection end
Connection closed

客户端输出

Connected to the server
Sent2 to server: First request
Server response: Hi, this is server response
Connection end
Connection closed
Connected2 to the server
Sent2 to server: Second request

预期运行结果

服务器输出

Received request:  First request
Connection end
Connection closed
Received request:  Second request
Connection end
Connection closed

客户端输出

Connected to the server
Sent2 to server: First request
Server response: Hi, this is server response
Connection end
Connection closed
Connected2 to the server
Sent2 to server: Second request
Server response: Hi, this is server response
Connection end
Connection closed

额外现象

当客户端挂起时终止脚本,服务器会打印错误并再次输出"Connection closed":

Server listening on 127.0.0.1:3000
Received request:  First request
Connection end
Connection closed
Socket error: Error: read ECONNRESET
    at TCP.onStreamRead (node:internal/stream_base_commons:220:20) {
  errno: -4077,
  code: 'ECONNRESET',
  syscall: 'read'
}
Connection closed

问题

为何错误后会出现"Connection closed"消息?是存在两个连接吗?还是第一次的Connection closed并未真正关闭连接?


问题根源与修复方案

  1. 客户端核心错误
    在runSecondConnection函数中,发送第二次请求时错误使用了第一个客户端的client对象,而非新创建的client2:
// 错误代码
client.write(msg);
// 正确代码
client2.write(msg);

这导致第二次请求根本没有通过新连接发送到服务器,客户端2一直等待响应,因此出现挂起现象。

  1. 服务器端冗余操作清理
  • socket.on('close')中调用socket.end()和socket.destroy()完全多余,close事件触发时连接已经处于关闭状态,这些操作不会产生任何效果。
  • socket.on('end')中调用socket.end()属于重复操作,end事件本身就是对方调用end()后触发的,此时socket已经进入关闭流程。

简化后的服务器端代码:

const net = require('net');
const serverAddress = '127.0.0.1';
const serverPort = 3000;

const server = net.createServer(socket => {
    socket.on('data', data => {
        console.log('Received request: ', data.toString())
        socket.write('Hi, this is server response');
    });
    socket.on('close', () => {
        console.log('Connection closed');
    });
    socket.on('end', () => {
        console.log('Connection end');
    });
    socket.on('error', error => {
        console.error('Socket error:', error);
    });
});

server.listen(serverPort, serverAddress, () => {
    console.log(`Server listening on ${serverAddress}:${serverPort}`);
});
  1. 错误后二次打印Connection closed的原因
    当终止挂起的客户端脚本时,第一个客户端连接因强制退出触发服务器端socket的ECONNRESET错误(表示连接被对方强制重置),而socket在触发error事件后会自动触发close事件,因此会再次打印"Connection closed"。这并非存在两个未关闭的连接,而是第一个连接的错误处理流程触发了第二次close事件。

内容的提问来源于stack exchange,提问作者Andrey Fedotov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 18:50:33