-
Notifications
You must be signed in to change notification settings - Fork 198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
看了好多遍都没看懂,这个地方没有错误吗 #87
Comments
每个流都是独立的,所以流之间乱序没有关系,这反而是shaper的目的,如果是单一流,可能确实肯定存在一个prio变量overflow导致的乱序问题。 |
又看了下代码在每个stream内部,使用的是numWritten作为writeRequest结构体中的prio,所以在stream内部怎么重新排列都可以保证发送的顺序。 这个问题可以关闭了。 感谢您的回复,您的代码让我学到了很多!
|
嗯,这个的prio溢出可能性是很高的,还是需要修复一下。 |
这个overflow的问题怎么保证呢,每个stream 发送 1 << 32 字节后就不行了。 |
因为stream.Write本身是阻塞函数,那么出现这个情况只可能是发送一个刚好在 1<<32附近的数据导致乱序,那么只需要做 无符号判断即可。 |
我怎么觉得这里的判断有问题呢? func _itimediff(later, earlier uint32) int32 { 比如说某stream用来传输一个大文件。 在这个stream 里,存在三个writeRequest 在队列里,分别为: 等待发送,最后一个溢出了。这样判断还还能保证顺序吗? 使用发送的字节数作为prio 真的合理吗? 在 shaperHeap 中存在很多这样的数据。 |
成立,你可以做 go test -v -run Shaper
数值32bit问题不大,很快就会回绕。 |
go test -run Shaper -v 您的意思是只要保证溢出数据附近的数据顺序正确就可以是吧。 |
有两个问题请您解答一下:
// internal writeFrame version to support deadline used in keepalive
func (s *Session) writeFrameInternal(f Frame, deadline <-chan time.Time, prio uint32) (int, error) {
req := writeRequest{
prio: prio,
frame: f,
result: make(chan writeResult, 1), //为什么要用带缓存的channel呢?这个地方直接make(chan writeResult)会影响速度吗?
} |
结果就一个,避免阻塞啊。 |
即使把所有的cmdPSH 数据的writeResult 的prio 设置为1,也能保证数据发送顺序
我做了个测试,某一个stream 里(sid相同)的数据,没有并发调用 Write(不应该并发调用吧?) 函数的情况下,实际上同一时刻只有一个cmdPSH数据 在shaperHeap队列里。即使把所有的cmdPSH 数据的writeResult 的prio 设置为1,也能保证数据发送顺序,不会出错。 您说的队列里可以有多个
|
把shaper.go中比较函数改成随机的,删除shaper_test.go,也能测试通过。 //shaper.go
package smux
import "math/rand"
func _itimediff(later, earlier uint32) int32 {
x := rand.Intn(2)
return int32(x)
// return (int32)(later - earlier)
} ··· |
都是正数,当然能过哈 |
无符号数转换为带符号数,比如uint32 1<<32 - 1 ,cast成 int32,就会负了。 |
//shaper.go
package smux
import "math/rand"
func _itimediff(later, earlier uint32) int32 {
x := rand.Intn(2)
return int32(x) // 这里返回0 或者1
// return (int32)(later - earlier)
} //shaper.go 这里比较的是大于0
func (h shaperHeap) Less(i, j int) bool { return _itimediff(h[j].prio, h[i].prio) > 0 } 因为 你的测试函数,TestWriteToV2,这里有比较发送和接受的数据是否一致,能测试通过说明数据顺序是正确的。原因就是某一个stream 在这个 shaperHeap []writeRequest 队列里,最多只有一个cmdPSH数据, func TestWriteToV2(t *testing.T) {
......
if bytes.Compare(sndbuf, rcvbuf.Bytes()) != 0 {
t.Fatal("mismatched echo bytes")
}
} 我的意思是说把s.numWritten 作为 writeFrameInternal函数的prio参数,并没有发挥作用啊。 func (s *Stream) writeV2(b []byte) (n int, err error) {
...
for len(bts) > 0 {
sz := len(bts)
if sz > s.frameSize {
sz = s.frameSize
}
frame.data = bts[:sz]
bts = bts[sz:]
n, err := s.sess.writeFrameInternal(frame, deadline, uint64(atomic.LoadUint32(&s.numWritten)))
atomic.AddUint32(&s.numWritten, uint32(sz))
sent += n
if err != nil {
return sent, err
}
}
} |
这个问题我想了很久也没想明白,恳请大侠指点一下。
因为我不相信这个程序这里会有错误。太抓狂了。
我的理解 有prio = 1 的一种数据 a1 a2 a3 a4 a5,prio =2 的一种数据 b1,b2,b3,b4,b5 。只要保证 prio相同的数据的发送顺序即可。a、b两种数据可以优先发送a数据。上面的操作把数据取出来,再放回去不是打算了数据a这种数据的顺序了吗?
我写了个小程序测试了一下。程序和结果如下:
结果是这样的:
The text was updated successfully, but these errors were encountered: