IMT星际源码 2018-10-30

序言

梁川,资深架构师,拥有10年以上一线技术从业经验。梁先生精通Erlang、python、Golang、java; 擅长各种平台高并发大流量架构设计与实施; 精通Ethereum区块链以及相关技术; 通读Go-Ethereum源码。

我们开辟《星际源码》专栏,请梁先生为我们讲讲高深的架构技术。梁先生将会不定期的随时分享他在工作中的感想与新知,希望与感兴趣的开发者朋友们一同学习成长!

go-libp2p-host Connect 源码分析

Connect 过程解析

•      go-libp2p-host中定义了Host接口,它有几个实现都在go-libp2p包中,我们关注basic包中的BasicHost实现,因为IPFS用了这个实现

•      Connect主要是dial peer并完成握手,再去交换Identify信息,Identify信息后文有提到,文中反复提到的ID是指Identify协议的名称

•      发起连接一端我们称为 from ,被连接一端成为 to ,则有如下过程在两端建立连接,这个时序图只为理解交互过程,对于阅读代码并无实际参考价值;

1、2是指from和to要先启动libp2p的host再做后续操作,在这一步已经执行了Swarm.Listen并启动了handlencoming线程来accept连接,并且为ID协议注册了StreamHandler,为通道上的连接注册了ConnHandler;

3 from端通过Connect来dial to端;

4、to端的newConnHandler被触发,这个方法调用了IdentifyConn;

5、于此同时from端发起连接请求成功后会去调用IdentifyConn;

6~14双方行为一致,握手成功后激活ID协议的StreamHandler触发requestHandler来向对方发送Identify消息,两端用各自的responseHandler来处理Identify消息,并将Identify信息放入peerstore中。

看代码,简单看一下 Connect 过程

首先看看接口怎么定义的,因为所有的逻辑都要建立在 Connect 的基础上,所以以 Connect 为入口来欣赏 BasicHost 的实现过程

Host 是什么以及 Connect 要做的事情通过注视都能看出来,只是看到 TODO 时感到有些遗憾,这个 Relay 足足耽误我几天时间,看来读代码应该先读接口.

From 端 Connect 的实现过程

注视跟接口描述的差不多,如果没有可用连接就会去尝试 dial 这个 peer 并且把它加入到 peerstore 中

dialPeer虽然很复杂但最终是调用到IdentifyConn方法上,我们直接看重点

To Listen 的实现过程

·BasicHost.NewHost

·Swarm.Listen

创建BasicHost时的net参数是Network接口的Swarm实现,那么启动过程中会调用Listen方法,下面代码贴出了关键部分,AddListenAddr方法的list.Accept()对上文提到的握手信息进行了处理,然后要upgrade这个连接,再去触发BasicHost中指定的net.SetConnHandler(h.newConnHandler)

Accept是Listener接口的方法

接口定义在go-libp2p-transport/transport.go中

实现定义在go-libp2p-transport-upgrader/listener.go中,我们看看如何实现

这个实现太简单了,只是在读incoming channel,所以线索是谁在往incoming chainnel中写数据,于是找到了handleIncoming()方法,以TcpTransport实现为例,可以看到是在UpgradeListener时启动的handleIncoming

以上已经把关键点都列出来了,略去了细节,如果想去扩展 go-libp2p 包调整握手协议组建私网等掌握这些内容应该已经够了。

你可能感兴趣的:(IMT星际源码 2018-10-30)