之前已经分析了ethereum的tcp通信的调用过程
现在来看tcp通信的底层编码
1.建立连接时的握手过程
握手完成是建立连接的前提,先看握手过程调用的入口
//p2p/server.go
func (srv *Server) setupConn(c *conn, flags connFlag, dialDest *discover.Node) error {
// Prevent leftover pending conns from entering the handshake.
srv.lock.Lock()
running := srv.running
srv.lock.Unlock()
if !running {
return errServerStopped
}
// Run the encryption handshake.
var err error
//debug.PrintStack()
//fmt.Println("setupConn diadest:", dialDest)
if c.id, err = c.doEncHandshake(srv.PrivateKey, dialDest); err != nil {
srv.log.Trace("Failed RLPx handshake", "addr", c.fd.RemoteAddr(), "conn", c.flags, "err", err)
//fmt.Println("Failed RLPx handshake", c.fd.RemoteAddr(), err)
return err
}
clog := srv.log.New("id", c.id, "addr", c.fd.RemoteAddr(), "conn", c.flags)
// For dialed connections, check that the remote public key matches.
if dialDest != nil && c.id != dialDest.ID {
clog.Trace("Dialed identity mismatch", "want", c, dialDest.ID)
//fmt.Println("setupConn 1", err)
return DiscUnexpectedIdentity
}
err = srv.checkpoint(c, srv.posthandshake)
if err != nil {
clog.Trace("Rejected peer before protocol handshake", "err", err)
//fmt.Println("setupConn 2", err)
return err
}
// Run the protocol handshake
phs, err := c.doProtoHandshake(srv.ourHandshake)
if err != nil {
clog.Trace("Failed proto handshake", "err", err)
//fmt.Println("setupConn ee 3", err)
return err
}
if phs.ID != c.id {
clog.Trace("Wrong devp2p handshake identity", "err", phs.ID)
//fmt.Println("setupConn 4", err)
return DiscUnexpectedIdentity
}
c.caps, c.name = phs.Caps, phs.Name
err = srv.checkpoint(c, srv.addpeer)
if err != nil {
clog.Trace("Rejected peer", "err", err)
//fmt.Println("setupConn 5", err)
return err
}
// If the checks completed successfully, runPeer has now been
// launched by run.
clog.Trace("connection set up", "inbound", dialDest == nil)
return nil
}
先看doEncHandshake方法
func (t *rlpx) doEncHandshake(prv *ecdsa.PrivateKey, dial *discover.Node) (discover.NodeID, error) {
var (
sec secrets
err error
)
######
如果是tcp服务端,接受tcp连接时
######
if dial == nil {
sec, err = receiverEncHandshake(t.fd, prv, nil)
} else {
######
如果是tcp客户端,主动进行连接
######
sec, err = initiatorEncHandshake(t.fd, prv, dial.ID, nil)
}
if err != nil {
//fmt.Println("doEncHandshake err", err, dial)
return discover.NodeID{}, err
}
t.wmu.Lock()
t.rw = newRLPXFrameRW(t.fd, sec)
t.wmu.Unlock()
return sec.RemoteID, nil
}