【问题标题】:How to make a node.js application keep listening after closing a socket?如何让 node.js 应用程序在关闭套接字后继续监听?
【发布时间】:2014-11-16 23:27:20
【问题描述】:

我正在尝试设置一个 node.js 应用程序,该应用程序可以接收连接并在套接字结束后仍监听端口 9001。我怎样才能做到这一点?这是我当前的代码(在 socket.end() 之后它不会关闭,但它不会接受任何其他连接):

var net = require('net');
var mySocket;

var server = net.createServer(function(socket) {
    mySocket = socket;
    mySocket.on("connect", onConnect);
    mySocket.on("data", onData);
});

function onConnect() {
    console.log("Connected");
}

function onData(command) {
    if (command == "exit") {
        console.log("Exiting");
        mySocket.end();
    }
}

console.log("Waiting for incoming connections");
server.listen(9001);

我试图在socket.end(); 之后添加另一个server.listen(9001);,但我收到一条:Error: listen EADDRINUSE 消息。 此外,该代码是否能够同时接收来自不同地址的多个连接,并分别处理它们?

这是完整的代码。执行时,node.js 接收到来自 Flash 应用程序的 4 个命令,并且正常工作(除了 onConnect() 函数似乎从未被调用),并且“exit;”命令正确关闭套接字,但如果我重新加载 Flash 应用程序,它不会连接到服务器

var net = require('net');
const PACKET_SEPARATOR = 59 // ;
var connection_ack = false;
var counter = 0;

var server = net.createServer(function(socket) {
    function onConnect() {
        console.log("Connected to Flash");
    }

    function dataHandler(command) {
        if (command[command.length - 1] != String.fromCharCode(PACKET_SEPARATOR) && connection_ack) {
       console.log("SEP : " + PACKET_SEPARATOR + " - last : " + command[command.length - 1] + " - ack " + connection_ack);
            console.log("CAUGHT EXCEPTION : WRONG PACKET FORMAT --- " + command + " --- " + command.length);
        }
        if (command == "exit;") {
            console.log("Received exit request from " + socket.address().address + ":" + socket.address().port + " (" + socket.address().family + "). Ending connection...");
            socket.end();
        }
        else if (command == "<policy-file-request/>\0") {
            socket.write('<cross-domain-policy>\n<allow-access-from domain="*" to-ports="*" />\n</cross-domain-policy>\0', 'utf8');
            console.log("Policy file sent to " + socket.address().address + ":" + socket.address().port);
            player1.pxacceleration = 0;
            player1.pyacceleration = 0;
            connection_ack = true;
        }
        else {
            console.log("Got data from " + socket.address().address + ":" + socket.address().port + " (" + socket.address().family + ")");
            console.log("--> " + command);
            counter++;
            socket.write("Received " + counter + " commands;", 'utf8');
            console.log("Sending : Received " + counter + " commands;");
        }
    }

    function onData(d) {
        var command = "";
        for (i=0; i <= d.length - 1; i++) {
            command += String.fromCharCode(d[i]);
            if (d[i] == PACKET_SEPARATOR || i == d.length - 1 && !connection_ack) {
                dataHandler(command);
                command = "";
            }
        }
    }

    socket.on("connect", onConnect);
    socket.on("data", onData);
});

console.log("Ready. Waiting for incoming connections");
server.listen(9001);
server.listen(80); //TODO : Remove?     

【问题讨论】:

  • 除非你关闭server,否则你想要的应该已经发生了。
  • server 应该已经比个人 sockets 寿命更长。对于多个客户端,server 将创建多个可以同时打开和活动的sockets。另一方面,全局 mySocket 无法帮助 server 正确支持多个客户端,因为它只能存储其中一个。
  • mySocket 用作全局非常糟糕。一旦您同时连接了多个套接字,您的 mySocket 变量就会被覆盖。使 onData 成为一个局部函数,您可以直接引用socket 而无需使用全局。
  • 我不确定你的意思。能给我举个小例子吗?

标签: node.js sockets loops


【解决方案1】:

正如jfriend00所说,不推荐使用mySocket作为全局。请尝试以下方法。

var server = net.createServer(function(socket) {
    function onData(command) {
        if (command == "exit") {
            console.log("Exiting");
            socket.end();
        }
    }
    socket.on("connect", onConnect);
    socket.on("data", onData);
});
...

这首先消除了对全局的需要。这也应该允许多个套接字并防止原始错误。我认为。我是新来的,所以我想我们会看到的。

编辑 好吧。我一直在通过 telnet 与您的代码进行交互。我还阅读了一些文档。首先,socket.on("connect", onConnect); 侦听器应该(连同onConnect 函数)移动到全局范围并更改为server.on("connection", onConnect);。原因是套接字事件侦听器connect 是客户端侦听器。我们在服务器端工作。新连接的服务器端监听器是connection,服务器应该像监听特定端口上的连接一样监听它。

这部分代码现在应该如下所示:

//more code up above here
....
    function onData(d) {
        var command = "";
        for (i=0; i <= d.length - 1; i++) {
            command += String.fromCharCode(d[i]);
            if (d[i] == PACKET_SEPARATOR || i == d.length - 1 && !connection_ack) {    
                dataHandler(command);
                command = "";
            }
        }
    }
    socket.on("data", onData);
});

function onConnect() {
    console.log("Connected to Flash");
}

server.on("connection", onConnect);
....
//more code below here

但是,代码无法将exit 识别为通过 telnet 的命令。我无法弄清楚这一点。由于您的问题未涵盖此问题,因此可能只是我,或者您已经弄清楚了。

编辑 2 下面的代码将其保留在本地。

var server = net.createServer(function(socket) {

    function onConnect() {
        console.log("Connected to Flash");
        socket.write("we're connected");
    }
....
    function onData(d) {
        var command = "";
        for (i=0; i <= d.length - 1; i++) {
            command += String.fromCharCode(d[i]);
            if (d[i] == PACKET_SEPARATOR || i == d.length - 1 && !connection_ack) {    
                dataHandler(command);
                command = "";
            }
        }
    }
    onConnect();
    socket.on("data", onData);
});

【讨论】:

  • 谢谢。我实施了您的解决方案,但仍然无法正常工作。我用完整的代码更新了我的问题
  • 谢谢!不过,我无法在全局范围内定义onConnect(),因为套接字仅在net.createServer(function(socket){...}) 内定义。我怎么能解决这个问题?还有,“出口”; command 只是我使用 Flash 发送的字符串。它可能是“退出”;或其他任何东西,这只是我的 Actionscript 程序现在使用的语法
  • 您可以将onConnect 函数留在本地范围内,然后在没有侦听器的情况下使用onConnect();,因为它只会在每次有新的套接字连接到服务器时才会被调用。我将相应地进行编辑,以便清楚。
  • 它现在几乎可以工作了,我每次都会收到“已连接到 Flash”的消息。剩下的唯一问题是onData() 侦听器在第一个套接字结束后没有重新创建(服务器不会对从 Flash 发送的任何数据作出反应,除非第一个套接字处于活动状态)。
  • 我已经能够通过 telnet 关闭和重新打开多个套接字。我无法复制您的错误。尝试使用socket.destroy(); 而不是socket.end();,看看会怎样。这完全破坏了套接字,通常仅用于故障排除。
猜你喜欢
  • 1970-01-01
  • 2015-11-30
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 2013-05-20
  • 1970-01-01
  • 2016-02-09
  • 1970-01-01
相关资源
最近更新 更多