本章将介绍tcp库的peer端,本节主要讲述connector端创建和收发信息


connector

type tcpConnector struct {
    peer.SessionManager

    peer.CorePeerProperty
    peer.CoreContextSet
    peer.CoreRunningTag
    peer.CoreProcBundle
    peer.CoreTCPSocketOption
    peer.CoreCaptureIOPanic

    defaultSes *tcpSession

    tryConnTimes int // 尝试连接次数

    sesEndSignal sync.WaitGroup

    reconDur time.Duration
}

tcpSession是负责处理消息接收。tcpSession的结构定义

type tcpSession struct {
    peer.CoreContextSet
    peer.CoreSessionIdentify
    *peer.CoreProcBundle

    pInterface cellnet.Peer

    // Socket原始连接
    conn      net.Conn
    connGuard sync.RWMutex

    // 退出同步器
    exitSync sync.WaitGroup

    // 发送队列
    sendQueue *cellnet.Pipe

    cleanupGuard sync.Mutex

    endNotify func()

    closing int64
}

tcpConnector 初始化连接。conn实例保存在tcpSession

// 连接器,传入连接地址和发送封包次数
func (self *tcpConnector) connect(address string) {

    self.SetRunning(true)

    for {
        self.tryConnTimes++

        // 尝试用Socket连接地址
        conn, err := net.Dial("tcp", address)

        self.defaultSes.setConn(conn)

        // 发生错误时退出
        if err != nil {

            if self.tryConnTimes <= reportConnectFailedLimitTimes {
                log.Errorf("#tcp.connect failed(%s) %v", self.Name(), err.Error())

                if self.tryConnTimes == reportConnectFailedLimitTimes {
                    log.Errorf("(%s) continue reconnecting, but mute log", self.Name())
                }
            }

            // 没重连就退出
            if self.ReconnectDuration() == 0 || self.IsStopping() {

                self.ProcEvent(&cellnet.RecvMsgEvent{
                    Ses: self.defaultSes,
                    Msg: &cellnet.SessionConnectError{},
                })
                break
            }

            // 有重连就等待
            time.Sleep(self.ReconnectDuration())

            // 继续连接
            continue
        }

        self.sesEndSignal.Add(1)

        self.ApplySocketOption(conn)

        self.defaultSes.Start()

        self.tryConnTimes = 0

        self.ProcEvent(&cellnet.RecvMsgEvent{Ses: self.defaultSes, Msg: &cellnet.SessionConnected{}})

        self.sesEndSignal.Wait()

        self.defaultSes.setConn(nil)

        // 没重连就退出/主动退出
        if self.IsStopping() || self.ReconnectDuration() == 0 {
            break
        }

        // 有重连就等待
        time.Sleep(self.ReconnectDuration())

        // 继续连接
        continue

    }

    self.SetRunning(false)

    self.EndStopping()
}
 self.defaultSes.Start()会开启两个goroutine,一个是发送循环,一个是接收循环
// 发送循环
func (self *tcpSession) sendLoop() {

    var writeList []interface{}

    var capturePanic bool

    if i, ok := self.Peer().(cellnet.PeerCaptureIOPanic); ok {
        capturePanic = i.CaptureIOPanic()
    }

    for {
        writeList = writeList[0:0]
        exit := self.sendQueue.Pick(&writeList)

        // 遍历要发送的数据
        for _, msg := range writeList {

            if capturePanic {
                self.protectedSendMessage(&cellnet.SendMsgEvent{Ses: self, Msg: msg})
            } else {
                self.SendMessage(&cellnet.SendMsgEvent{Ses: self, Msg: msg})
            }
        }

        if exit {
            break
        }
    }

    // 完整关闭
    conn := self.Conn()
    if conn != nil {
        conn.Close()
    }

    // 通知完成
    self.exitSync.Done()
}
// 接收循环
func (self *tcpSession) recvLoop() {

    var capturePanic bool

    if i, ok := self.Peer().(cellnet.PeerCaptureIOPanic); ok {
        capturePanic = i.CaptureIOPanic()
    }

    for self.Conn() != nil {

        var msg interface{}
        var err error

        if capturePanic {
            msg, err = self.protectedReadMessage()
        } else {
            msg, err = self.ReadMessage(self)
        }

        if err != nil {
            if !util.IsEOFOrNetReadError(err) {

                var ip string
                if self.conn != nil {
                    addr := self.conn.RemoteAddr()
                    if addr != nil {
                        ip = addr.String()
                    }
                }

                log.Errorf("session closed, sesid: %d, err: %s ip: %s", self.ID(), err, ip)
            }

            self.sendQueue.Add(nil)

            // 标记为手动关闭原因
            closedMsg := &cellnet.SessionClosed{}
            if self.IsManualClosed() {
                closedMsg.Reason = cellnet.CloseReason_Manual
            }

            self.ProcEvent(&cellnet.RecvMsgEvent{Ses: self, Msg: closedMsg})
            break
        }

        self.ProcEvent(&cellnet.RecvMsgEvent{Ses: self, Msg: msg})
    }

    // 通知完成
    self.exitSync.Done()
}

self.ProcEvent函数会调用proc.BindProcessorHandler的第三个参数,也就是用户自定义的数据处理函数,下面是一个例子。用户可以根据自己的需要自定义数据处理函数

proc.BindProcessorHandler(peerIns, "tcp.ltv", func(ev cellnet.Event) {

        switch msg := ev.Message().(type) {
        case *cellnet.SessionConnected: // 已经连接上
            fmt.Println("client connected")
            ev.Session().Send(&TestEchoACK{
                Msg:   "hello",
                Value: 1234,
            })
        case *TestEchoACK: //收到服务器发送的消息

            fmt.Printf("client recv %+v\n", msg)

            // 完成操作
            done <- struct{}{}

        case *cellnet.SessionClosed:
            fmt.Println("client closed")
        }
    })

以上就是一条信息处理的主要步骤。


lyh1091106900
1 声望0 粉丝