Node.js 中的同步 TCP 读取

Jac*_*her 5 javascript tcp boost-asio node.js

有没有办法在 node.js 中同步读取 TCP 套接字?

我很清楚如何通过向套接字的“数据”事件添加回调来异步执行此操作:

socket.on('data', function(data) {
    // now we have the string data to do whatever with
});
Run Code Online (Sandbox Code Playgroud)

我也知道尝试使用函数调用进行阻塞而不是注册回调有悖于 node 的设计,但是我们正在尝试更新一个旧的 node 模块,该模块充当我大学的客户端,同时保持向后兼容性。所以我们目前有:

var someData = ourModule.getData();
Run Code Online (Sandbox Code Playgroud)

getData()以前有一帮其背后的逻辑,但现在我们只想发送到服务器“运行的getData()”,并等待结果。这样所有的逻辑都是服务器端,而不是重复的客户端和服务器端。这个模块已经维护了一个到服务器的 TCP 连接,所以我们只是捎带它。

以下是我尝试过的解决方案:

  1. 为隐藏在 node 的 net 模块中类似于 python 的套接字库的某处的套接字找到一个阻塞读取函数。

    string_from_tcp = socket.recv(1024)
    
    Run Code Online (Sandbox Code Playgroud)

    这里的问题是它似乎不存在(不出所料,因为它违背了 node 的意识形态)。

  2. 这个同步网络模块添加了我需要的东西,但没有 Windows 支持;所以我必须补充一点。

  3. 找到一个允许节点解除事件循环阻塞的函数,然后返回,这样就可以了:

    var theData = null;
    clientSocket.on('data', function(data) {
        theData = data;
    });
    
    clientSocket.write("we want some data");
    
    while(theData === null) {
        someNodeFunctionThatUnblocksEventLoopThenReturnsHere(); // in this function node can check the tcp socket and call the above 'data' callback, thus changing the value of theData
    }
    
    // now theData should be something!
    
    Run Code Online (Sandbox Code Playgroud)

    这里明显的问题是我认为不存在这样的事情。

  4. 使用 ECMAScript 6 生成器函数:

    var stringFromTcp = yield socketRead(1024);
    
    Run Code Online (Sandbox Code Playgroud)

    这里的问题是我们会强迫学生将他们的 JavaScript 客户端更新为这种新语法,而理解 ES6 超出了使用它的课程的范围。

  5. 使用 node-gyp 并向我们的 node 模块添加一个到 C++ TCP 库的接口,该库支持同步读取,例如 boost 的 asio。这可能会奏效,但让 node 模块与 boost 跨平台编译一直是一个巨大的痛苦。所以我来到 Stack Overflow 是为了确保我没有把这个问题复杂化。

用最简单的术语来说,我只是想创建一个支持同步 tcp 读取的命令行 JavaScript 程序。

那么还有其他想法吗?如果这在节点项目的上下文中看起来亵渎神明,请提前抱歉,并感谢您的任何意见。

Jac*_*her 5

我最终选择了选项 5。我在 C++ ( netLink ) 中找到了一个小巧、快速且易于构建的 TCP 库,并为它编写了一个节点模块包装器,名为netlinkwrapper

该模块构建在 Windows 和 Linux 上,但由于它是一个 C++ 插件,您需要配置 node-gyp 来构建它。

我希望没有其他人像我使用这个模块那样使用 Node.js,但如果你必须用 TCP 调用阻塞事件循环,这可能是你唯一的赌注。