每个坑都是成长的一小步,初学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方法来读取。
庆幸自己是在写自己的代码时提前遇到这个坑...,又可以愉快的继续了
网友评论