月度归档: 2017 年 6 月

Node.js socket stream 和异步函数

考虑如下实现场景:
使用 Node.js 实现一个服务端,客户端使用 Socket 连接之后处理数据并返回。
其中,处理数据的场景中很容易出现异步函数(比如数据库查询,或者读配置文件),导致还没把 chunk 处理完,pipe就跑到下一步去了,导致客户端直接被关掉了。
查了一晚上 so 和各种官方 github ,最后还是通过读官方文档解决了。
先给出解决方案。
在 Create Server 的时候,设置 allowHalfOpen 为 true 。
官方对这一参数的解释是:
allowHalfOpen Indicates whether half-opened TCP connections are allowed. See net.createServer() and the 'end' event for details. Defaults to false.
就是允许创建的 Socket 处于半开模式(数据流暂时停止而连接仍然建立)。这样的话,就可以让处理器 (parser) 放心地去处理数据,等返回后再将处理过的 chunk 吐回到 pipe 中。
不过有一点需要注意,如果允许了 HalfOpen ,那么就一定要在处理完数据后手动关掉 Socket ,也就是文中所说的调用 Socket.end() 方法,否则的话 tcp 连接就无法正常结束了。

exp.
简单实现场景:


const server = net.createServer({allowHalfOpen :true}, (socket) => {
    socket.once('error', (err) => {
        console.log('[ERROR]');
    });

    socket
        .pipe(...)
        .pipe(through2(function(chunk,enc,callback){
            let _this = this;
            _parser.parseData(chunk).then(function(chunk){
                _this.push(chunk);
                socket.end();
            }).catch(function(err){
                _this.push(err);
                socket.end();
            });
        }))
        .pipe(...)
    .pipe(socket);
});
server.listen(..., ..., () => {
    console.log('[INFO]');
});

其中,parseData是一个使用了 asnyc 方法的函数。