// peekMessageSize() reads, but not commits, enough bytes to determine the size of // the next message and returns the type and size. func (this *service) peekMessageSize() (message.MessageType, int, error) { var ( b []byte err error cnt int = 2 ) if this.in == nil { err = ErrBufferNotReady return 0, 0, err } // Let's read enough bytes to get the message header (msg type, remaining length) for { // If we have read 5 bytes and still not done, then there's a problem. if cnt > 5 { return 0, 0, fmt.Errorf("sendrecv/peekMessageSize: 4th byte of remaining length has continuation bit set") } // Peek cnt bytes from the input buffer. b, err = this.in.ReadWait(cnt) if err != nil { return 0, 0, err } // If not enough bytes are returned, then continue until there's enough. if len(b) < cnt { continue } // If we got enough bytes, then check the last byte to see if the continuation // bit is set. If so, increment cnt and continue peeking if b[cnt-1] >= 0x80 { cnt++ } else { break } } // Get the remaining length of the message remlen, m := binary.Uvarint(b[1:]) // Total message length is remlen + 1 (msg type) + m (remlen bytes) total := int(remlen) + 1 + m mtype := message.MessageType(b[0] >> 4) return mtype, total, err }
// processor() reads messages from the incoming buffer and processes them func (this *service) processor() { defer func() { // Let's recover from panic if r := recover(); r != nil { Log.Errorc(func() string { return fmt.Sprintf("(%s) Recovering from panic: %v", this.cid(), r) }) } this.wgStopped.Done() Log.Debugc(func() string { return fmt.Sprintf("(%s) Stopping processor", this.cid()) }) this.stop() }() this.wgStarted.Done() for { // 1. Find out what message is next and the size of the message p, ok := this.in.ReadBuffer() if !ok { Log.Debugc(func() string { return fmt.Sprintf("(%s) suddenly disconnect.", this.cid()) }) return } mtype := message.MessageType((*p)[0] >> 4) _p := this.server.getRealBytes(p) msg, err := mtype.New() n, err := msg.Decode(_p) //清理指针p //p = nil _p = nil this.server.DestoryBytes(*p) if err != nil { Log.Errorc(func() string { return fmt.Sprintf("(%s) Error peeking next message: %v", this.cid(), err) }) return } // this.rmu.Unlock() //Log.Debugc(func() string{ return fmt.Sprintf("(%s) Received: %s", this.cid(), msg)}) this.inStat.increment(int64(n)) // 5. Process the read message err = this.processIncoming(msg) if err != nil { if err != errDisconnect { Log.Errorc(func() string { return fmt.Sprintf("(%s) Error processing %s: %v", this.cid(), msg.Name(), err) }) } else { return } } // 7. Check to see if done is closed, if so, exit if this.isDone() { return } } }