Node.js:客户端没有';TCP连接关闭时不会死掉
我在Node.js中构建了一个简单的TCP服务器和一个简单的TCP客户端 现在,当客户端向服务器发送“exit”时,连接成功关闭。服务器从其套接字列表中删除套接字,并向客户端发送“再见!” 客户端上的连接也已关闭,但应用程序仍在等待其他输入,因此它不会死掉,我被迫键入CTRL+C 我尝试在连接关闭后添加Node.js:客户端没有';TCP连接关闭时不会死掉,node.js,tcpclient,Node.js,Tcpclient,我在Node.js中构建了一个简单的TCP服务器和一个简单的TCP客户端 现在,当客户端向服务器发送“exit”时,连接成功关闭。服务器从其套接字列表中删除套接字,并向客户端发送“再见!” 客户端上的连接也已关闭,但应用程序仍在等待其他输入,因此它不会死掉,我被迫键入CTRL+C 我尝试在连接关闭后添加process.exit(),但不起作用: 客户端代码: var net = require('net'), config = require(__dirname + '/config.j
process.exit()
,但不起作用:
客户端代码:
var net = require('net'),
config = require(__dirname + '/config.json'),
connection = net.createConnection(config.port, config.host);
connection.setEncoding('utf8');
connection.on('connect', function () {
console.log('Connected');
});
connection.on('error', function (err) {
console.error(err);
});
connection.on('data', function (data) {
console.log('» ' + data);
});
connection.on('close', function() {
console.log('Connection closed');
});
process.stdin.on('data', function (data) {
if ((new String(data)).toLowerCase() === 'exit') {
connection.end();
process.exit();
}
else {
connection.write(data);
}
});
process.stdin.resume();
var server = require('net').createServer(),
config = require(__dirname + '/config.json'),
sockets = [];
server.on('connection', function (socket) {
socket.setEncoding('UTF-8');
socket.on('data', function (data) {
console.log('Received data: ' + data);
if (data.trim().toLowerCase() === 'exit') {
socket.write("Bye bye!\n");
socket.end();
}
else {
sockets.forEach(function (client) {
if (client && client != socket) {
client.write(data);
}
});
}
});
socket.on('close', function () {
console.log('Connection closed');
sockets.splice(sockets.indexOf(socket), 1);
console.info('Sockets connected: ' + sockets.length);
});
sockets.push(socket);
});
server.on('listening', function () {
console.log('Server listening');
});
server.on('close', function () {
console.log('Server is now closed');
});
server.on('error', function (err) {
console.log('error:', err);
});
server.listen(config.port);
connection.on('close', function() {
console.log('Connection closed');
process.exit();
});
服务器代码:
var net = require('net'),
config = require(__dirname + '/config.json'),
connection = net.createConnection(config.port, config.host);
connection.setEncoding('utf8');
connection.on('connect', function () {
console.log('Connected');
});
connection.on('error', function (err) {
console.error(err);
});
connection.on('data', function (data) {
console.log('» ' + data);
});
connection.on('close', function() {
console.log('Connection closed');
});
process.stdin.on('data', function (data) {
if ((new String(data)).toLowerCase() === 'exit') {
connection.end();
process.exit();
}
else {
connection.write(data);
}
});
process.stdin.resume();
var server = require('net').createServer(),
config = require(__dirname + '/config.json'),
sockets = [];
server.on('connection', function (socket) {
socket.setEncoding('UTF-8');
socket.on('data', function (data) {
console.log('Received data: ' + data);
if (data.trim().toLowerCase() === 'exit') {
socket.write("Bye bye!\n");
socket.end();
}
else {
sockets.forEach(function (client) {
if (client && client != socket) {
client.write(data);
}
});
}
});
socket.on('close', function () {
console.log('Connection closed');
sockets.splice(sockets.indexOf(socket), 1);
console.info('Sockets connected: ' + sockets.length);
});
sockets.push(socket);
});
server.on('listening', function () {
console.log('Server listening');
});
server.on('close', function () {
console.log('Server is now closed');
});
server.on('error', function (err) {
console.log('error:', err);
});
server.listen(config.port);
connection.on('close', function() {
console.log('Connection closed');
process.exit();
});
编辑:
var net = require('net'),
config = require(__dirname + '/config.json'),
connection = net.createConnection(config.port, config.host);
connection.setEncoding('utf8');
connection.on('connect', function () {
console.log('Connected');
});
connection.on('error', function (err) {
console.error(err);
});
connection.on('data', function (data) {
console.log('» ' + data);
});
connection.on('close', function() {
console.log('Connection closed');
});
process.stdin.on('data', function (data) {
if ((new String(data)).toLowerCase() === 'exit') {
connection.end();
process.exit();
}
else {
connection.write(data);
}
});
process.stdin.resume();
var server = require('net').createServer(),
config = require(__dirname + '/config.json'),
sockets = [];
server.on('connection', function (socket) {
socket.setEncoding('UTF-8');
socket.on('data', function (data) {
console.log('Received data: ' + data);
if (data.trim().toLowerCase() === 'exit') {
socket.write("Bye bye!\n");
socket.end();
}
else {
sockets.forEach(function (client) {
if (client && client != socket) {
client.write(data);
}
});
}
});
socket.on('close', function () {
console.log('Connection closed');
sockets.splice(sockets.indexOf(socket), 1);
console.info('Sockets connected: ' + sockets.length);
});
sockets.push(socket);
});
server.on('listening', function () {
console.log('Server listening');
});
server.on('close', function () {
console.log('Server is now closed');
});
server.on('error', function (err) {
console.log('error:', err);
});
server.listen(config.port);
connection.on('close', function() {
console.log('Connection closed');
process.exit();
});
我添加了一个客户端连接“on close”事件处理程序。因此,字符串“Connection closed”(连接已关闭)现在由服务器和客户端打印。我怀疑if((新字符串(数据)).toLowerCase()==='exit')
是否成功,因为data
很可能有一个尾随的换行符(在服务器中,在进行比较之前,您trim()
,但在客户端中没有)
如果解决了这个问题,您就会遇到一个逻辑问题:当获取“退出”时,您会关闭连接,而不会向服务器发送“退出”,因此查找“退出”的服务器代码将永远不会执行。尝试在服务器中使用事件:“关闭”:
您必须将
process.exit()
指令仅放在最后一个事件处理程序上。因此,在这种情况下,您必须将其放在客户端连接“on close”事件处理程序中:
客户端:
var net = require('net'),
config = require(__dirname + '/config.json'),
connection = net.createConnection(config.port, config.host);
connection.setEncoding('utf8');
connection.on('connect', function () {
console.log('Connected');
});
connection.on('error', function (err) {
console.error(err);
});
connection.on('data', function (data) {
console.log('» ' + data);
});
connection.on('close', function() {
console.log('Connection closed');
});
process.stdin.on('data', function (data) {
if ((new String(data)).toLowerCase() === 'exit') {
connection.end();
process.exit();
}
else {
connection.write(data);
}
});
process.stdin.resume();
var server = require('net').createServer(),
config = require(__dirname + '/config.json'),
sockets = [];
server.on('connection', function (socket) {
socket.setEncoding('UTF-8');
socket.on('data', function (data) {
console.log('Received data: ' + data);
if (data.trim().toLowerCase() === 'exit') {
socket.write("Bye bye!\n");
socket.end();
}
else {
sockets.forEach(function (client) {
if (client && client != socket) {
client.write(data);
}
});
}
});
socket.on('close', function () {
console.log('Connection closed');
sockets.splice(sockets.indexOf(socket), 1);
console.info('Sockets connected: ' + sockets.length);
});
sockets.push(socket);
});
server.on('listening', function () {
console.log('Server listening');
});
server.on('close', function () {
console.log('Server is now closed');
});
server.on('error', function (err) {
console.log('error:', err);
});
server.listen(config.port);
connection.on('close', function() {
console.log('Connection closed');
process.exit();
});
不久前,在改进模块的测试套件时,我遇到了同样的问题。在所有测试都通过之后,nodeunit进程没有退出,因为node cubrid正在使用
connection.end()
在超时时关闭客户端套接字,就像您所做的那样
然后我使用connection.end()
和connection.destroy()
,这是一种更干净的方法,可以确保套接字真正关闭而不终止正在运行的进程,我认为这是比上面建议的process.exit()
更好的解决方案。因此,在您的客户机代码上下文中,我将执行以下操作:
process.stdin.on('data', function (data) {
if ((new String(data)).toLowerCase() === 'exit') {
connection.destroy();
}
else {
connection.write(data);
}
});
根据:
socket.destroy()
确保此套接字上不再发生I/O活动。仅在出现错误(解析错误等)时才需要
我想你在找这个:socket.unref() 从Node.js文档(): socket.unref()# 如果该套接字是事件系统中唯一的活动套接字,则调用套接字上的unref将允许程序退出。如果套接字已被unref,则再次调用unref将无效
(新字符串(数据)).toLowerCase()工作正常,因为连接将成功关闭,事实上,服务器会向客户端发送“再见!”并打印“连接已关闭\n连接的套接字:0”。。。因此,客户端已断开连接,服务器正在侦听将来的连接,但客户端进程(不是连接)仍处于活动状态。我尝试了
connection.destroy()
方法,但在我的应用程序中,结果是相同的。它会关闭连接,例如connection.end()
does。关键是,在连接关闭后,进程仍在运行,只有在connection.end()或connection.destroy()之后调用的process.exit()
才能提供所需的行为。请读我的答案。您必须将进程.exit()
仅放在连接.on('close')
事件处理程序中,因此在连接关闭(或销毁)后。在命令行上尝试我的代码。close
事件在调用end()
时不会立即激发。当套接字实际关闭时调用它,例如在end()
之后服务器说bye
(这是来自服务器的+1个数据包),或者在destroy()
之后立即调用,这会强制断开连接。一旦套接字关闭,即在close
事件处理程序中,process.exit(),或者客户端没有死掉,您必须按CTRL+C快捷键才能在shell上键入内容。这就是问题所在,只有process.exit()
指令可以在我发布的代码中修复此行为。如果您找到了另一种方法来修复我的应用程序上的特定行为,请发布此消息。connection.destroy()
没有修复我的挂起行为。我刚试过。