Node.js:客户端没有';TCP连接关闭时不会死掉

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

我在Node.js中构建了一个简单的TCP服务器和一个简单的TCP客户端

现在,当客户端向服务器发送“exit”时,连接成功关闭。服务器从其套接字列表中删除套接字,并向客户端发送“再见!”

客户端上的连接也已关闭,但应用程序仍在等待其他输入,因此它不会死掉,我被迫键入CTRL+C

我尝试在连接关闭后添加
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()
没有修复我的挂起行为。我刚试过。