说明:此文章为腾讯云机器自动从本人csdn博客搬迁过来。是本人授权操作。
申明:无本人授权,不可转载本文。如有转载,本人保留追究其法律责任的权利。
龚浩华,QQ 29185807,月牙寂 道长
第一时间获取文章,可以关注本人公众号 月牙寂道长 yueyajidaozhang
上一篇分析了p2p模块的初始化与start。 继续上一篇分析。
先回顾下p2p的初始化
github.com/ethereum/go-ethereum/eth/backend.go中
函数
func New(config *Config) (*Ethereum, error) {
下面是start
那现在进入到p2p模块中
github.com/ethereum/go-ethereum/p2p/server.go中
在p2p模块中,大部分的数据是通过chan来进行传输的。以上有7个chan
上面是关键地方,两个入口。
下面分别介绍
Listen部分
继续跟踪
这里面有slots,是用来做数量限制的。用了一个带缓冲区的chan,先讲token放进去,然后先取出token,接收一个链接,当链接ok了后,将token放回去。
很简单的chan的应用
那么逻辑还是很清晰的,我们继续跟踪
这里面的东西就比较多了。一个一个来
先看下两个函数的原型doEncHandshake和doProtoHandshake
在586行,c := &conn{fd: fd, transport: srv.newTransport(fd), flags: flags, cont: make(chan error)}
我们看下srv的
然后我们回到func (srv *Server) Start() (err error) {
那么就知道了
github.com/ethereum/go-ethereum/p2p/rlpx.go中
真正的处理函数在这里
github.com/ethereum/go-ethereum/p2p/rlpx.go
github.com/ethereum/go-ethereum/p2p/rlpx.go
好的回到func (srv *Server) setupConn(fd net.Conn, flags connFlag, dialDest *discover.Node) {
中
github.com/ethereum/go-ethereum/p2p/server.go
我们看下
在函数func (srv *Server) setupConn(fd net.Conn, flags connFlag, dialDest *discover.Node) {
if err := srv.checkpoint(c, srv.posthandshake); err != nil {
if err := srv.checkpoint(c, srv.addpeer); err != nil {
分别传递的是两个chan,srv.posthandshak和srv.addpee
好的,到这里listen的处理就完了。下面我们看如何通过chan与run进行配合工作的。
github.com/ethereum/go-ethereum/p2p/server.go中
上面的重点到了,通过chan的传送,把数据传到run中,处理
上面才是重点。Addpeer。
github.com/ethereum/go-ethereum/p2p/peer.go
传入的参数,protocol是srv.Protocols。这个我们在第一篇文章中有说到。
继续跟踪
github.com/ethereum/go-ethereum/p2p/server.go中
继续
github.com/ethereum/go-ethereum/p2p/peer.go
重点三个地方,慢慢来看
很简单的读信息,然后进行处理
继续
上面的重点处理都在default中,这个就是最上层的入口
好的重点来了。跟踪进去,完了,好像看不懂
重点是在p.running
我们回过头去看看
我们知道初始化peer的时候,传送的是srv.Protocols。这个在第一篇文章有介绍了,
回到
这个很简单,定时的pingpong
我们看看最初的run在哪里
github.com/ethereum/go-ethereum/eth/handler.go
ProtocolManager初始化Protocols的时候