簡體   English   中英

Node.js:TCP連接關閉時客戶端不會死亡

[英]Node.js: client doesn't die when TCP connection closes

我在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”現在由服務器和客戶端打印。

我想你正在尋找這個:socket.unref()。

從Node.js文檔( https://nodejs.org/api/net.html#net_socket_unref ):

socket.unref()#

如果這是事件系統中唯一的活動套接字,則在套接字上調用unref將允許程序退出。 如果套接字已經unfd,則再次調用unref將無效。

前段時間在改進node-cubrid模塊的測試套件時,遇到了同樣的問題。 在所有測試都通過之后,nodeunit進程沒有退出,因為node-cubrid在發生超時時使用connection.end()來關閉客戶端套接字,就像你一樣。

然后我 connection.end() 替換connection.destroy() ,這是一種更簡潔的方法來確保套接字真正關閉而不實際終止正在運行的進程,我認為這是比上面建議的process.exit()更好的解決方案process.exit() 所以,在你的客戶端代碼上下文中,我會這樣做:

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

根據Node.js文檔

socket.destroy()

確保此套接字上不再發生I / O活動。 僅在出現錯誤時才需要(解析錯誤等)。

我懷疑if ((new String(data)).toLowerCase() === 'exit')是否成功,因為data很可能有一個尾隨換行符(在你的服務器中,你在做比較之前trim() ,但不是客戶端)。

如果這已經解決了,你就會遇到一個邏輯問題:當你“退出”時你關閉連接而不向服務器發送“退出”,所以尋找“退出”的服務器代碼將永遠不會執行。

嘗試使用事件:服務器中的“關閉”: http//nodejs.org/api/net.html#net_event_close

您必須將process.exit()指令僅放在最后一個事件處理程序上。 因此,在這種情況下,您必須將其放在客戶端連接“on close”事件處理程序中:

客戶:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM