【问题标题】:How to code two-way duplex streams in NodeJS如何在 NodeJS 中编写双向双工流
【发布时间】:2013-10-24 11:18:31
【问题描述】:

在 NodeJS 的最新几个版本(撰写本文时为 v0.10.X)中,Streams API 进行了受欢迎的重新设计,我想现在开始使用它。

我想用一个实现协议的对象来包装套接字的输入 输出。

所谓的Duplex接口,似乎就是任何可读可写的流(如socket)。

尚不清楚 Duplexes 应该像 A 还是 B,或者它是否无关紧要。

   +---+        +---+
-->| A |-->     |   |-->
   +---+        | B |
                |   |<--
                +---+

对于具有两个可写和两个可读对象的正确代码结构/接口是什么?

+--------+   +----------+   +----
|       r|-->|w        r|-->|w    
| socket |   | protocol |   | rest of app
|       w|<--|r        w|<--|r    
+--------+   +----------+   +----

上图的问题是protocol对象需要两个独立的read方法和两个write方法。

在我的脑海中,我可以让协议产生“左”和“右”双工对象,或“输入”和“输出”双工对象(以不同的方式对其进行切片)。

这些是首选方式,还是有更好的解决方案?

【问题讨论】:

    标签: node.js sockets stream duplex


    【解决方案1】:
              |      app      |
              +---------------+
                  ^       |
                  |       V      
               +-----+ +-----+
               |     | |     |
    +----------|     |-|     |-+
    | protocol | .up | |.down| |
    +----------|     |-|     |-+
               |     | |     |
               +-----+ +-----+
                  ^       |
                  |       V
              +---------------+
              |     socket    |
    

    我的解决方案是创建一个 Protocol 类,它创建了一个 Up Transform 和一个 Down Transform

    Protocol 构造函数在构造 Up 和 Down 转换时传递一个引用(对自身)。然后,每个向上和向下转换中的_transform 方法可以在其自身上调用push,在另一个Transform 上调用,或根据需要同时调用两者。公共状态可以保存在Protocol 对象中。

    【讨论】:

    • +1,我认为“up”和“down”是个好名字,因为它可以代表抽象级别。您可以通过管道传输每一层的所有上行通道,也可以通过管道传输下行通道。但是,我认为同时使用基本的 pipe2 和 unpipe2 方法会很有用。
    【解决方案2】:

    双工流就像您的图表 B,至少对于用户而言。更完整的流视图将包括生产者(源)和消费者(用户)。请参阅我以前的answer。尽量不要从消费者的角度考虑读/写。

    您正在做的是在套接字上为协议构建一个薄层,因此您的设计是正确的:

                             -------+     +----------+     +------
                                   r|---->|         r|---->|      
                             socket |     | protocol |     | rest of app
                                   w|<----|         w|<----|      
                             -------+     +----------+     +------
    

    您可以对协议部分使用双工或转换。

                     +---------+--------+---------+       +------------------+ 
                     | _write->|        |         |r      |   Transform  ->  |r
                     |-----------Duplex-----------|       +------------------+    
                     |         |        | <-_read |w      |   <- Transform   |w
                     +---------+--------+---------+       +------------------+
    

    使用内部 _read、_write 处理传入/传出数据的协议相关处理。或者您可以转换流。您可以通过管道将协议传递给套接字,将套接字传递给协议。

    【讨论】:

    • 协议需要在两个转换之间共享状态。最好如何做到这一点?
    • 您可以设置标志来表示状态或在流中存储数据。请参阅simpleprotocolv2 示例。你可以用这些this._sawFirstCr = false; this._rawHeader = [];
    • 对于您的任务,最好使用双工来完成,因为两个流都可以轻松看到标志。对于转换,您必须为两个流设置两次标志。
    • 我的意思是协议中有两个紧密相连的变换。来自套接字的数据包可能会导致将数据包发送到套接字和/或将数据包发送到应用程序。同样,来自应用程序的数据包可能会导致数据包被发送到套接字和/或数据包被发送到应用程序。
    猜你喜欢
    • 2020-03-03
    • 1970-01-01
    • 2016-07-30
    • 2019-03-18
    • 1970-01-01
    • 2019-04-08
    • 2021-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多