美文网首页
记一次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的入坑经历

    每个坑都是成长的一小步,初学go,于是想把srs用go重写下,练练手;完成信令部分后,美滋滋以为可以接着下一步处理...

  • Go Context的踩坑经历

    转载 Go Context 踩坑经历

  • 入坑Go

  • Moya:入坑记

    Moya:入坑记

  • “入坑”经历

    整体来说,小A是一个容易被蛊惑的人。只要这件事情符合她的价值观,她是很容易被说服的。而且很少能一直坚定的坚持自己的...

  • Go Context的踩坑经历

    Go Context的踩坑经历https://studygolang.com/articles/12566

  • Go语言入坑

    GO语言基础 认识并安装GO语言开发环境 Go语言简介 Go语言是谷歌2009年发布的第二款开源编程语言 go语言...

  • 从此,我的世界多了一份牵挂

    新手养肉记 大家都称养多肉叫入坑,那我入坑资历还是比较浅的。时间虽短,但经历也还算丰富,一路走来也有跌跌撞撞,困难...

  • Go语言在Mac(osx系统)上的安装配置

    最近入职的公司做区块链,开始接触到了Go语言,第一次配置就比较尴尬,决定记录一下坑吧。 1. 首先翻墙去下载Go ...

  • 记一次go尝试经历

    初学go,确实go在网络开发方面提供的很多便捷 自动化的编译工具,一个go build搞定一切 丰富的标准库,几乎...

网友评论

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

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