多路复用和多流之间的区别

Difference between multiplex and multistream

多流(yamux、multistream-select、..)和多路复用(mplex)有什么区别? 我想为 RPC、HTTP 等使用一个 TCP 连接(一个客户端在防火墙后面),如下所示:

conn = tcp.connect("server.com:1111")
conn1, conn2 = conn.split()

stream1 = RPC(conn1)
stream2 = WebSocket(conn2)
..

// received packets tagged for conn1 is forwarded to stream1
// received packets tagged for conn2 is forwarded to stream2
// writing to stream1 tags the packets for conn1
// writing to stream2 tags the packets for conn2

哪种适合这种情况?

简短的回答:mplex 和 yamux 都是流多路复用器(又名流复用器),它们负责在单个 "raw" 连接(例如 TCP)上交错多个 "logical streams"。 Multistream 用于 识别 在通过流发送/接收数据时应使用哪种协议, multistream-select 让对等方 协商 每一端都支持哪些协议,并希望就一个协议达成一致。

长答案:

流混合是 interface with several implementations. The "baseline" stream muxer is called mplex - a libp2p-specific protocol with implementations in javascript, go and rust

流多路复用器是 "pluggable",这意味着您可以通过拉入模块并配置 libp2p 应用程序来使用它们来添加对它们的支持。给定的 libp2p 应用程序可以同时支持多个多路复用器,例如,您可以使用 yamux 作为默认设置,但也支持 mplex 与不支持 yamux 的对等方通信。

虽然拥有这种灵活性很好,但这也意味着我们需要一种方法来确定要为任何特定连接使用哪种流复用器。这就是 multistream 和 multistream-select 发挥作用的地方。

Multistream(尽管名称如此)与流多路复用没有直接关系。相反,它充当二进制数据流的 "header",使用协议 ID 将流上下文化。密切相关的 multistream-select 协议使用 mutlistream 协议 id 来协商用于 "next phase" 通信的协议。

因此,为了就使用哪种流混合器达成一致,我们使用 multistream-select。

这是一个多流-select 来回的例子:

/multistream/1.0.0 <- dialer says they'd like to use multistream 1.0.0
/multistream/1.0.0 -> listener echoes back to indicate agreement
/secio/1.0.0       <- dialer wants to use secio 1.0.0 for encryption
/secio/1.0.0       -> listener agrees

* secio handshake omitted. what follows is encrypted via secio: *

/mplex/6.7.0       <- dialer would like to use mplex 6.7.0 for stream multiplexing
/mplex/6.7.0       -> listener agrees

这是一个简单的案例,双方都同意一切 - 例如,如果监听器不支持 /mplex/6.7.0,他们可以用 na(不可用)响应,拨号器可以尝试另一种协议,通过发送 ls 请求支持的协议列表,或放弃。

在上面的示例中,双方就 mplex 达成一致,因此未来通过开放连接进行的通信将受制于 mplex 的语义。

请务必注意,在 libp2p 中打开单个连接时,上面的大部分详细信息将主要 "invisible" 给您,因为很少直接使用多流和流复用库。

相反,名为 "switch"(在某些实现中也称为 "swarm")的 libp2p 组件管理应用程序的拨号/收听状态。交换机处理多流协商过程和"hides"正在使用来自 libp2p 堆栈其余部分的特定流复用器的详细信息。

作为 libp2p 开发人员,您通常使用交换机接口拨打其他点,这将为您提供一个流来读取和写入。在引擎盖下,交换机将找到合适的传输(例如 TCP / websockets)并使用 multistream-select 来协商加密和流多路复用。如果您已经打开了与远程对等点的连接,交换机将只使用现有连接并在其上打开另一个多路流,而不是从头开始。

侦听连接也是如此 - 您为交换机提供一个协议 ID 和一个流处理函数,它将为您处理多路复用和协商过程。

我们的文档还在制作中,但 https://docs.libp2p.io that might help clarify, especially the concept doc on Transports and the glossary. You can also find links to example code 中有一些信息。

改进 libp2p 的文档是我目前的主要任务,所以请随时在 https://github.com/libp2p/docs 提交问题,让我知道您最重要的遗漏部分是什么。