JavaScript:查找本地 WebSocket 服务器

trv*_*rvo 2 javascript websocket

我目前正在尝试检测 IP 范围内的本地网络 websocket 服务器(我编写的)。我有一个在网络上运行,我希望我的脚本能够检测到它(以及在同一端口上的其他脚本)。

目前,我可以使用 for 循环完成此操作,然后尝试根据我是否可以成功连接到该 IP 上的服务器来创建一个列表。然而,这是非常缓慢和低效的。任何想法如何快速有效地做到这一点?

我的代码片段:

var port = 1234;
var ip_range = "192.168.1.";
var servers = [];
var i = 0;

function findServers() {
    if ( i > 255 ) {
        return;
    }
    try {
        var host = "ws://"+ip_range+i+":"+port;
        var socket = new WebSocket(host);
        socket.onopen = function(){
            console.log("Success: " + socket.url);
            servers.push(socket.url);
            i++;
            findServers();
        };
        socket.onerror = function(error){
            console.log("Error: " + socket.url);
            i++;
            findServers();
        };
    } catch (e) {
        console.log("Error: " + socket.url);
        i++;
        findServers();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果有帮助,我编写了套接字服务器,以便在需要时修改代码。

jfr*_*d00 5

像您一样通过试用套接字连接获得快速结果的关键有两个:

  1. 并行运行多个连接尝试(尽可能多,但不要太多)
  2. 控制不存在的服务器的超时时间(WebSocket 内置的默认超时时间很长,因此这缩短了长时间等待,这使得检查大量套接字的整个过程(其中大多数不存在)需要很长时间时间)。

你不必使用 WebWorkers 来完成这个任务,事实上,我认为使用 WebWorkers 可能效率较低,因为不需要为每个套接字创建一个新线程。Javascript 中的 Socket 编程是完全异步的,因此您可以让它们中的许多同时正常运行并且非常高效。

这是一种完全异步的方式,可以同时运行多个套接字请求,并且应该比使用 WebWorker 更有效。可能需要进行一些实验才能查看一次可以打开多少个活动的 WebSocket 请求。此示例将 20 作为该参数传递,但您可以尝试更多或更少。越多越好(并行请求越多),直到您一次遇到活动套接字的浏览器限制。

获得结果的速度的一个关键参数是设置等待 webSocket 响应多长时间的超时值。在这个实现中,我让您将其作为参数传递,您可以再次尝试使用适当的值。由于这些都是本地服务器,您正在寻找,我希望几秒钟(2000-4000 毫秒)可能对您有用,并且生成的结果比正常的 WebSocket 超时要快得多。

function findServers(port, ipBase, ipLow, ipHigh, maxInFlight, timeout, cb) {
    var ipCurrent = +ipLow, numInFlight = 0, servers = [];
    ipHigh = +ipHigh;

    function tryOne(ip) {
        ++numInFlight;
        var address = "ws://" + ipBase + ip + ":" + port;
        var socket = new WebSocket(address);
        var timer = setTimeout(function() {
            console.log(address + " timeout");
            var s = socket;
            socket = null;
            s.close();
            --numInFlight;
            next();
        }, timeout);
        socket.onopen = function() {
            if (socket) {
                console.log(address + " success");
                clearTimeout(timer);
                servers.push(socket.url);
                --numInFlight;
                next();
            }
        };
        socket.onerror = function(err) {
            if (socket) {
                console.log(address + " error");
                clearTimeout(timer);
                --numInFlight;
                next();
            }
        }
    }

    function next() {
        while (ipCurrent <= ipHigh && numInFlight < maxInFlight) {
            tryOne(ipCurrent++);
        }
        // if we get here and there are no requests in flight, then
        // we must be done
        if (numInFlight === 0) {
            console.log(servers);
            cb(servers);
        }
    }

    next();
}

findServers(1234, "192.168.1.", 1, 255, 20, 4000, function(servers) {
    console.log(servers);
});
Run Code Online (Sandbox Code Playgroud)