简短的回答:mplex 和 yamux 都是流复用器(又名流复用器),它们负责在单个“原始”连接(例如 TCP)上交错多个“逻辑流”。Multistream 用于确定通过流发送/接收数据时应使用哪种协议,multistream-select 让对等方协商每一端支持哪些协议,并希望就使用哪种协议达成一致。
长答案:
流复用是一个具有多种实现的接口。“基线”流复用器称为 mplex - 一种特定于 libp2p 的协议,在javascript、go和rust中实现。
流多路复用器是“可插入的”,这意味着您可以通过拉入一个模块并配置您的 libp2p 应用程序来使用它们来添加对它们的支持。给定的 libp2p 应用程序可以同时支持多个多路复用器,例如,您可以使用 yamux 作为默认值,但也支持 mplex 与不支持 yamux 的对等方通信。
虽然拥有这种灵活性是很好的,但这也意味着我们需要一种方法来确定用于任何特定连接的流复用器。这就是多流和多流选择的用武之地。
Multistream(尽管有名字)与流复用没有直接关系。相反,它充当二进制数据流的“标头”,将流与协议 id 关联起来。密切相关的多流选择协议使用多流协议 id 来协商用于“下一阶段”通信的协议。
因此,为了就使用什么流复用器达成一致,我们使用多流选择。
这是一个来回多流选择的示例:
/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 中打开单个连接时,上述大部分细节对您来说大多是“不可见的”,因为很少直接使用多流和流复用库。
相反,一个名为“switch”(在某些实现中也称为“swarm”)的 libp2p 组件管理应用程序的拨号/侦听状态。该开关处理多流协商过程,并从 libp2p 堆栈的其余部分“隐藏”正在使用的特定流复用器的详细信息。
作为一个 libp2p 开发人员,您通常使用 switch 接口拨打其他对等方,这将为您提供读取和写入的流。在底层,交换机会找到合适的传输(例如 TCP / websockets)并使用多流选择来协商加密和流多路复用。如果您已经与远程对等方建立了开放连接,则交换机将仅使用现有连接并在其上打开另一个多路复用流,而不是从头开始。
监听连接也是如此——你给交换机一个协议 id 和一个流处理函数,它会为你处理复用和协商过程。
我们的文档正在进行中,但https://docs.libp2p.io上的一些信息可能有助于澄清,尤其是有关 Transports和词汇表的概念文档。您还可以找到示例代码的链接。
改进 libp2p 的文档是我目前的主要任务,因此请随时在https://github.com/libp2p/docs上提出问题,让我知道您最重要的缺失部分是什么。