// Read implements net.Conn
func (s *UDPSession) Read(b []byte) (n int, err error) {
    for {
        s.mu.Lock()
        //判断缓存是否有数据 如果有从缓存中读取到b中
        if len(s.bufptr) > 0 { // copy from buffer into b
            n = copy(b, s.bufptr)
            s.bufptr = s.bufptr[n:]
            s.mu.Unlock()
            return n, nil
        }
        //判断如果当前session已经关闭那么就返回错误
        if s.isClosed {
            s.mu.Unlock()
            return 0, errors.New(errBrokenPipe)
        }

        if size := s.kcp.PeekSize(); size > 0 { // peek data size from kcp
            atomic.AddUint64(&DefaultSnmp.BytesReceived, uint64(size))
            if len(b) >= size { // direct write to b
                s.kcp.Recv(b)
                s.mu.Unlock()
                return size, nil
            }

            // resize kcp receive buffer
            // to make sure recvbuf has enough capacity
            if cap(s.recvbuf) < size {
                s.recvbuf = make([]byte, size)
            }

            // resize recvbuf slice length
            s.recvbuf = s.recvbuf[:size]
            s.kcp.Recv(s.recvbuf)
            n = copy(b, s.recvbuf)   // copy to b
            s.bufptr = s.recvbuf[n:] // update pointer
            s.mu.Unlock()
            return n, nil
        }

        // read deadline
        var timeout *time.Timer
        var c <-chan time.Time
        if !s.rd.IsZero() {
            if time.Now().After(s.rd) {
                s.mu.Unlock()
                return 0, errTimeout{}
            }

            delay := s.rd.Sub(time.Now())
            timeout = time.NewTimer(delay)
            c = timeout.C
        }
        s.mu.Unlock()

        // wait for read event or timeout
        select {
        case <-s.chReadEvent:
        case <-c:
        case <-s.die:
        case err = <-s.chErrorEvent:
            if timeout != nil {
                timeout.Stop()
            }
            return n, err
        }

        if timeout != nil {
            timeout.Stop()
        }
    }
}

PeekSize()


// PeekSize checks the size of next message in the recv queue
func (kcp *KCP) PeekSize() (length int) {
//如果接收队列为空就返回-1
    if len(kcp.rcv_queue) == 0 {
        return -1
    }
    //取出接收队列的数据
    seg := &kcp.rcv_queue[0]
    if seg.frg == 0 {
        return len(seg.data)
    }

    if len(kcp.rcv_queue) < int(seg.frg+1) {
        return -1
    }

    for k := range kcp.rcv_queue {
        seg := &kcp.rcv_queue[k]
        length += len(seg.data)
        if seg.frg == 0 {
            break
        }
    }
    return
}

results matching ""

    No results matching ""