【问题标题】:How can I check if port is busy in NodeJS?如何检查 NodeJS 中的端口是否繁忙?
【发布时间】:2021-09-06 00:42:19
【问题描述】:

如何检查localhost端口是否繁忙

有没有标准算法?我正在考虑向该网址发出http 请求并检查响应状态代码是否不是404

【问题讨论】:

标签: javascript node.js


【解决方案1】:

您可以尝试启动服务器,无论是 TCP 还是 HTTP,都没有关系。然后你可以尝试开始监听一个端口,如果失败,检查错误码是不是EADDRINUSE

var net = require('net');
var server = net.createServer();

server.once('error', function(err) {
  if (err.code === 'EADDRINUSE') {
    // port is currently in use
  }
});

server.once('listening', function() {
  // close the server if listening doesn't fail
  server.close();
});

server.listen(/* put the port to check here */);

使用一次性事件处理程序,您可以将其包装到异步检查函数中。

【讨论】:

  • 这不适用于未使用 SO_REUSEADDR 的服务器。查看github.com/baalexander/node-portscanner 了解他们如何使用net.Socket() 解决此问题。
  • 你也应该等到服务器关闭...通过监听服务器关闭事件server.once('close', () => { myFunc() }).close()
  • 启动这样的临时服务器可能会导致多线程环境中的不良竞争条件(例如 Jest 测试运行程序)。想象一下,如果一个线程启动一个临时服务器,同时另一个线程尝试启动一个“永久”测试服务器。在这一点上,事情可能会很快变得混乱。
【解决方案2】:

查看惊人的tcp-port-used node module

//Check if a port is open
tcpPortUsed.check(port [, host]) 

 //Wait until a port is no longer being used
tcpPortUsed.waitUntilFree(port [, retryTimeMs] [, timeOutMs])

//Wait until a port is accepting connections
tcpPortUsed.waitUntilUsed(port [, retryTimeMs] [, timeOutMs])

//and a few others!

我已经在我的gulpwatch 任务中使用这些来检测我的 Express 服务器何时安全终止以及何时再次启动。

这将准确报告端口是否已绑定(无论SO_REUSEADDRSO_REUSEPORT,如@StevenVachon 所述)。

portscanner NPM module 将在范围内为您找到空闲和使用的端口,如果您试图找到要绑定的开放端口,它会更有用。

【讨论】:

  • 这个解决方案在我的 prod 环境中造成了很多麻烦tcpPortUsed 在侦听 telnet 的端口应答时显示端口正在使用。我有一项服务只接受一个连接并拒绝 telnet。在这种情况下,它返回端口未使用。
  • @DavutGürbüz 很遗憾听到 - 你能解释一下吗? tcpPortUsed 尝试与端口建立 TCP 连接(不是 telnet - 尽管 telnet 做同样的事情)。如果它能够建立连接,则该端口正在使用中。如果不是,则端口是空闲的。所以我不确定你的意思 - 服务在接受它之前无法知道 TCP 连接是来自 telnet 还是来自其他任何东西。
  • 这就是我要说的。在我的 TCP Server 应用程序中,我将连接数限制为 1。所以,我猜这个库无法建立到指定端口的连接,它认为端口未在使用中。
  • 哦!我现在知道了。那真不幸。我想在这种情况下对您来说更好的解决方案是简单地尝试打开端口 - 尽管我相信根据端口的打开方式,这也有一个边缘情况
  • 如果端口是用SO_REUSEPORTSO_REUSEADDR 打开的,那么该端口可能会被多个应用程序打开——尽管您不太可能在您的情况下设置这个。只是另一个需要考虑的极端情况
【解决方案3】:

感谢 Steven Vachon 链接,我做了一个简单的例子:

const net = require("net");
const Socket = net.Socket;

const getNextPort = async (port) => {
    return new Promise((resolve, reject) => {
        const socket = new Socket();

        const timeout = () => {
            resolve(port);
            socket.destroy();
        };

        const next = () => {
            socket.destroy();
            resolve(getNextPort(++port));
        };

        setTimeout(timeout, 200);
        socket.on("timeout", timeout);

        socket.on("connect", function () {
            next();
        });

        socket.on("error", function (exception) {
            if (exception.code !== "ECONNREFUSED") {
                reject(exception);
            } else {
                next();
            }
        });

        socket.connect(port, "0.0.0.0");
    });
};

getNextPort(8080).then(port => {
    console.log("port", port);
});

【讨论】:

  • 谢谢,这行得通
猜你喜欢
  • 1970-01-01
  • 2014-06-17
  • 2013-02-08
  • 1970-01-01
  • 2019-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多