美文网首页
记一次go的入坑经历

记一次go的入坑经历

作者: hijiang | 来源:发表于2019-06-14 00:27 被阅读0次

    每个坑都是成长的一小步,初学go,于是想把srs用go重写下,练练手;完成信令部分后,美滋滋以为可以接着下一步处理媒体数据了。
    结果发现经常握手完成后,程序卡主了,一直等待读取头部一字节,但是从wireshark抓包上看,前端已经将握手后的第一个请求【releaseStream命令】发给服务器了。
    于是netstat查看Recv-Q,发现内核已经没有数据,Recv-Q是0了。
    百思不得其解,于是strace看看程序在干嘛,发现居然在futex等待,嗯,也正常,没数据就等待。
    左看又看还是看不出问题:

    func (this *SrsHandshakeBytes) ReadC2() int {
        if len(this.C2) > 0 {
            return -1
        }
    
        this.C2 = make([]byte, 1536)
        // (*c).SetReadDeadline(time.Now().Add(1000*time.Millisecond))
        reader := bufio.NewReader(*this.conn)
        left := 1536
        for {
            n, err := reader.Read(this.C2[1536-left:1536])//(*this.conn).Read(this.C2[1536-left:1536])
            if err != nil {
                return -1
            }
            log.Print("read n=", n)
            left = left - n
            if left <= 0 {
                return 0
            }
        }
    }
    

    最后,怀疑到了bufio是不是用得不对上,于是翻了下go手册:

    func (b *Reader) Size() [int]
    
    Size returns the size of the underlying buffer in bytes.
    

    也就是说,这个bufio生成的reader,就算读取了想要的数据,有可能还会有剩余(它会尽量将可读数据都读到buf中),难怪读不到后面的数据程序卡住,于是打印看看是不是读完之后还有剩余数据:

    func (this *SrsHandshakeBytes) ReadC2() int {
        if len(this.C2) > 0 {
            return -1
        }
    
        this.C2 = make([]byte, 1536)
        // (*c).SetReadDeadline(time.Now().Add(1000*time.Millisecond))
        reader := bufio.NewReader(*this.conn)
        left := 1536
        for {
            n, err := reader.Read(this.C2[1536-left:1536])//(*this.conn).Read(this.C2[1536-left:1536])
            if err != nil {
                return -1
            }
            log.Print("read n=", n)
            left = left - n
            if left <= 0 {
                log.Print("left size=", reader.Size())
                return 0
            }
        }
    }
    
    2019/06/06 19:32:50 start rtmp server
    2019/06/06 19:32:50 read xxxxx n=1537
    2019/06/06 19:32:50 write s0s1s2 succeed, count=%!(EXTRA int=3073)
    2019/06/06 19:32:50 read n=1536
    2019/06/06 19:32:50 left size=4096
    2019/06/06 19:32:50 HandShake Succeed
    2019/06/06 19:32:50 start RecvNewMessage
    2019/06/06 19:32:50 start ReadBasicHeader
    2019/06/06 19:32:50 start read 1 bytes
    

    结果left size=4096,确实把后续的数据都给读走了。
    解决方法:
    直接使用net.Conn的Read方法来读取。
    庆幸自己是在写自己的代码时提前遇到这个坑...,又可以愉快的继续了

    相关文章

      网友评论

          本文标题:记一次go的入坑经历

          本文链接:https://www.haomeiwen.com/subject/tejyfctx.html