在上文的介绍中,出现了多处有关p2p通信协议的结构类型,比如eth.peer,p2p.Peer,Server等等。这里不妨对这些p2p通信协议族的结构一并作个总解。以太坊中用到的p2p通信协议族的结构类型,大致可分为三层:

第一层处于pkg eth中,可以直接被eth.Ethereum,eth.ProtocolManager等顶层管理模块使用,在类型声明上也明显考虑了eth.Ethereum的使用特点。典型的有eth.peer{}, eth.peerSet{},其中peerSet是peer的集合类型,而eth.peer代表了远端通信对象和其所有通信操作,它封装更底层的p2p.Peer对象以及读写通道等。
第二层属于pkg p2p,可认为是泛化的p2p通信结构,比较典型的结构类型包括代表远端通信对象的p2p.Peer{}, 封装自更底层连接对象的conn{},通信用通道对象protoRW{}, 以及启动监听、处理新加入连接或断开连接的Server{}。这一层中,各种数据类型的界限比较清晰,尽量不出现揉杂的情况,这也是泛化结构的需求。值得关注的是p2p.Protocol{},它应该是针对上层应用特意开辟的类型,主要作用包括容纳应用程序所要求的回调函数等,并通过p2p.Server{}在新连接建立后,将其传递给通信对象peer。从这个类型所起的作用来看,命名为Protocol还是比较贴切的,尽管不应将其与TCP/IP协议等既有概念混淆。
第三层处于golang自带的网络代码包中,也可分为两部分:第一部分pkg net,包括代表网络连接的<Conn>接口,代表网络地址的<Addr>以及它们的实现类;第二部分pkg syscall,包括更底层的网络相关系统调用类等,可视为封装了网络层(IP)和传输层(TCP)协议的系统实现。
下列UML图描绘了上述三层p2p通信协议族中的一些主要结构,希望对于理解以太坊中p2p通信相关代码有所帮助。



小结:
诸如以太坊这种去中心化的数字货币运行系统,天生适用p2p通信架构。不过原理虽然简单,在系统架构的层面,依然有很多实现细节需要加以关注。

eth.ProtocolManager中,会对每一个远端peer发起主动传输数据的操作,这组操作按照数据类型区分,可分为交易和区块;而若以发送数据方式来区分,亦可分为广播单项数据,和同步一组同类型数据。这样两两配对,即可形成4组主动传输数据的操作。
ProtocolManager通过在p2p.Protocol{}对象中埋入回调函数,可以对远端peer的任何事件及状态更新作出响应。这些Protocol对象,会由p2p.Server传递给每一个新连接上的远端peer。
以太坊目前实现的p2p通信协议族的结构类型中,按照功能和作用,可分为三层:顶层pkg eth中的类型直接服务于当前以太坊系统(Ethereum,ProtocolManager等模块),中间层pkg p2p是泛化结构类型,底层包括golang语言包自带的pkg net, syscall等,封装了网络层和传输层协议的系统实现。