Node.js:TCP连接关闭时客户端不会死亡

时间:2012-10-24 12:14:51

标签: node.js tcpclient

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

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

客户端上的连接也已关闭,但应用程序仍在等待其他输入,因此它不会死,我不得不键入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 closed”现在由服务器和客户端打印。

5 个答案:

答案 0 :(得分:4)

我认为你正在寻找这个:socket.unref()。

来自Node.js文档(https://nodejs.org/api/net.html#net_socket_unref):

  

socket.unref()#

     

如果这是事件系统中唯一的活动套接字,则在套接字上调用unref将允许程序退出。如果套接字已经unfd,则再次调用unref将无效。

答案 1 :(得分:2)

前段时间改进node-cubrid模块的测试套件时,我遇到了同样的问题。在所有测试都通过之后,nodeunit进程没有退出,因为node-cubrid在发生超时时使用connection.end()关闭客户端套接字,就像你一样。

然后我replaced connection.end()使用connection.destroy(),这是一种更清晰的方法,可以确保套接字真正关闭而不会实际终止正在运行的进程,我认为,是比上面提到的process.exit()更好的解决方案。因此,在您的客户端代码上下文中,我会这样做:

process.stdin.on('data', function (data) {
    if ((new String(data)).toLowerCase() === 'exit') {
       connection.destroy();
    }
    else {
       connection.write(data);
    }
});

根据Node.js documentation

  

<强> socket.destroy()

     

确保此套接字上不再发生I / O活动。仅在出现错误时才需要(解析错误等)。

答案 2 :(得分:0)

我怀疑if ((new String(data)).toLowerCase() === 'exit')是否成功,因为data很可能有一个尾随换行符(在您的服务器中,您在进行比较之前是trim(),而不是在客户端中)。

如果修复了,你就会遇到一个逻辑问题:当你“退出”时你关闭连接而不向服务器发送“退出”,所以寻找“退出”的服务器代码永远不会执行。

答案 3 :(得分:0)

尝试使用事件:服务器中的“关闭”: http://nodejs.org/api/net.html#net_event_close

答案 4 :(得分:0)

您必须仅将process.exit()指令放在最后一个事件处理程序上。因此,在这种情况下,您必须将其放在客户端连接“on close”事件处理程序中:

<强>客户端:

connection.on('close', function() {
    console.log('Connection closed');
    process.exit();
});