NodeJS在动态路由上显示实时TCP数据

时间:2018-01-31 06:49:03

标签: javascript node.js tcp

我的最终目标如下:我的园丁有几个设备可以通过TCP将数据发送到我的Node.js服务器。此数据采用JSON格式,如下所示:

设备A:

{"pagename": "spacekittens", "count": 11};

设备B:

{"pagename": "norwegiansultans", "count": 22};

由于每个都通过TCP流式传输到我的服务器,我添加了;来分隔每个流。此外,每个设备流中的count是随机生成的。

现在,我想为我的每个TCP数据包添加动态路由,并将该流中的内容显示到该路由。

所以我的路线myserver:4000/spacekittens应该显示以下内容:

{"pagename": "spacekittens", "count": [random number every second]};

我的路线myserver:4000/norwegiansultans应该显示:

{"pagename": "norwegiansultans", "count": [random number every second]};

为了实现这个目的,我设置了以下代码:

server.on("connection", function(socket) {
    let chunk = "";
    socket.on('data', function(data) {
        chunk += data.toString(); // Add string on the end of the variable 'chunk'
        let d_index = chunk.indexOf(';'); // Find the delimiter

        // While loop to keep going until no delimiter can be found
        while (d_index > -1) {
            try {
                let string = chunk.substring(0, d_index); // Create string up until the delimiter

                // define local variables that can be used in a closure
                let json = JSON.parse(string); // Parse the current string
                let localData = data;
                console.log(json.pagename); // Function that does something with the current chunk of valid json.    
                app.get("/" + json.pagename, function(req, res) {
                    res.writeHead(200, {
                        'Content-Type': 'text/plain'
                    });
                    res.write(JSON.stringify(json));
                    res.end();
                });
            } catch (e) {
                console.log(e);
            }
            chunk = chunk.substring(d_index + 1); // Cuts off the processed chunk
            d_index = chunk.indexOf(';'); // Find the new delimiter
        }
    });
    socket.on("close", function() {
        console.log("connection closed");
    });
});

我很欣赏有关我想要完成的方法的任何想法和评论。但是,由于这个原因,我没有张贴。我有个问题。

目前,我的res.write()行仅填充路线中的数据一次。通过套接字添加新数据不会替换路由中的内容。

所以在myserver:4000/spacekittens路线下我的count显示11,即使我流式传输了更新的号码("count": 12),我的路线myserver:4000/spacekittens仍然只显示11.控制台记录让我每次发送数据时的正确响应。所以我没有正确使用res.write(),因为它不会覆盖旧数据。

不确定如何纠正。

1 个答案:

答案 0 :(得分:1)

我会从连接处理中分离页面数据和路由设置。每次收到JSON blob时都不能设置相同的路由,因此这会修改应用程序路由以将数据返回给用户。数据将随每个JSON blob而变化。

class Pages {

    constructor(app){
        this._store = {}
        this.app = app
    }

    get( name ){
        return this._store[name]
    }

    set( name, data ){
        if ( !this.exists(name) ) this.setupRoute(name)
        return this._store[name] = data
    }

    exists( name ){
        return this._store.hasOwnProperty(name)
    }

    addJSON( json_string ){
        let data = JSON.parse(json_string)
        if ( !data.pagename ) throw new Error('No pagename in data: "%s"', json_string)
        if ( !data.count ) throw new Error('No count in data "%s"', json_string)
        return this.set(data.pagename, data)
    }

    setupRoute( name ){
        let route = `/${name}`
        this.app.get(route, (req, res)=>{
            res.json(this.get(name))
        })
        console.log('setup route: %s', route)
        return this.app
    }

}

然后连接处理只处理为Pages拉出JSON字符串。

const pages = new Pages(app)

server.on("connection", function(socket) {
    let chunk = "";

    socket.on('data', function(data) {
        chunk += data.toString(); // Add string on the end of the variable 'chunk'
        let d_index = chunk.indexOf(';'); // Find the delimiter

        // While loop to keep going until no delimiter can be found
        while (d_index > -1) {
            try {
                let string = chunk.substring(0, d_index); // Create string up until the delimiter
                pages.addJSON(string)
            } catch (e) {
                console.error(e);
            }
            chunk = chunk.substring(d_index + 1); // Cuts off the processed chunk
            d_index = chunk.indexOf(';'); // Find the new delimiter
        }
    });

    socket.on("close", function() {
        console.log("connection closed");
    });
});

您还可以使用其中一个行分隔的JSON解析库,它将采用二进制流并将JSON作为普通对象发出:

ndjsonld-jsonstream