Closed chen2ding closed 7 months ago
See #573
func (uc *UlebCodec) ReadULEB128(conn gnet.Conn) ([]byte, error) {
bodyLen := 0
ulebLen := 1
for {
if ulebLen > 5 {
break
}
buf, err := conn.Peek(ulebLen)
// 连接中没有数据
if err != nil || len(buf) != ulebLen {
return nil, nil
}
v := 0
cc := 0
for _, b := range buf {
v += (int(b) & 0x7F) << cc
cc += 7
if b&0x80 == 0 {
bodyLen = v
break
}
}
// uleb 读取完整退出循环
if bodyLen > 0 {
break
}
ulebLen++
}
defer conn.Discard(bodyLen + ulebLen)
//等待读取bodyLen
if bodyLen > uc.readBuffSize {
return nil, fmt.Errorf("abnormal msg bodyLen:%d > readBuffSize:%d", bodyLen, uc.readBuffSize)
}
buf, _ := conn.Peek(ulebLen + bodyLen)
//PrintHex(buf[ulebLen:])
return buf[ulebLen:], nil
}
同样的代码,v1升级V2后不能正常工作,上面是V2代码,下面v1
func (uc *UlebCodec) ReadULEB128(conn gnet.Conn) ([]byte, error) {
bodyLen := 0
ulebLen := 1
for {
if ulebLen > 5 {
break
}
n, buf := conn.ReadN(ulebLen)
// 连接中没有数据
if n == 0 || n != ulebLen {
return nil, nil
}
v := 0
cc := 0
for _, b := range buf {
v += (int(b) & 0x7F) << cc
cc += 7
if b&0x80 == 0 {
bodyLen = v
break
}
}
// uleb 读取完整退出循环
if bodyLen > 0 {
break
}
ulebLen++
}
defer conn.ShiftN(bodyLen + ulebLen)
//等待读取bodyLen
if bodyLen > uc.readBuffSize {
return nil, fmt.Errorf("abnormal msg bodyLen:%d > readBuffSize:%d", bodyLen, uc.readBuffSize)
}
_, buf := conn.ReadN(ulebLen + bodyLen)
return buf[ulebLen:], nil
}
🤖 Non-English text detected, translating...
func (uc *UlebCodec) ReadULEB128(conn gnet.Conn) ([]byte, error) { bodyLen := 0 ulebLen := 1 for { ifulebLen > 5 { break } buf, err := conn.Peek(ulebLen) // There is no data in the connection if err != nil || len(buf) != ulebLen { return nil, nil } v := 0 cc := 0 for , b := range buf { v += (int(b) & 0x7F) << cc cc += 7 if b&0x80 == 0 { bodyLen = v break } } // uleb reads completely and exits the loop if bodyLen > 0 { break } ulebLen++ } defer conn.Discard(bodyLen + ulebLen) //Waiting to read bodyLen if bodyLen > uc.readBuffSize { return nil, fmt.Errorf("abnormal msg bodyLen:%d > readBuffSize:%d", bodyLen, uc.readBuffSize) } buf, := conn.Peek(ulebLen + bodyLen) //PrintHex(buf[ulebLen:]) return buf[ulebLen:], nil } The same code, v1 cannot work properly after upgrading to V2. The above is the V2 code, and the following v1
func (uc *UlebCodec) ReadULEB128(conn gnet.Conn) ([]byte, error) { bodyLen := 0 ulebLen := 1 for { ifulebLen > 5 { break } n, buf := conn.ReadN(ulebLen) // There is no data in the connection if n == 0 || n != ulebLen { return nil, nil } v := 0 cc := 0 for _, b := range buf { v += (int(b) & 0x7F) << cc cc += 7 if b&0x80 == 0 { bodyLen = v break } } // uleb reads completely and exits the loop if bodyLen > 0 { break } ulebLen++ } defer conn.ShiftN(bodyLen + ulebLen) //Waiting to read bodyLen if bodyLen > uc.readBuffSize { return nil, fmt.Errorf("abnormal msg bodyLen:%d > readBuffSize:%d", bodyLen, uc.readBuffSize) } _, buf := conn.ReadN(ulebLen + bodyLen) return buf[ulebLen:], nil }
@panjf2000 请问这是什么问题呢
🤖 Non-English text detected, translating...
@panjf2000 What is the problem?
@panjf2000 调试感觉是buf中的数据我没有读完,然后后面就不触发OnTraffic了,v1版本正常的
🤖 Non-English text detected, translating...
@panjf2000 The debugging feeling is that I haven’t finished reading the data in buf, and then OnTraffic will not be triggered later. The v1 version is normal.
First format your code, it's unreadable.
@panjf2000 已经格式化了,麻烦看下上面代码呢
🤖 Non-English text detected, translating...
@panjf2000 It has been formatted. Please take a look at the above code.
One of the best practices with gnet
v2 is to keep reading and decoding packets until you reach an incomplete packet, otherwise the OnTraffic
won't be invoked again until there is new arrival of data on the socket. I think the root cause of your issue here is that gnet
v1 would loop reading and decoding packets internally while gnet
v2 wouldn't.
🤖 Non-English text detected, translating...
One of the best practices with v2
gnet
is to continue reading and decoding packets until an incomplete packet arrives, otherwise not callingOnTraffic
again until new data arrives on the socket. I think the root cause of your problem is thatgnet
v1 internally loops reading and decoding packets, whilegnet
v2 does not.
I can confirm that the v1 version is not reading in the inner loop, the decode code is above This is the V1 outer code
func (s *Server) React(frame []byte, c gnet.Conn) (out []byte, action gnet.Action) {
msg := BinaryJson.DecodeGJson(frame)
if msg == nil {
action = gnet.Close
return
}
client, ok := c.Context().(*Client)
if !ok || client == nil {
return
}
task := func() {
msgType, _ := msg.GetInt("t")
switch msgType {
case rpc.PingMsg:
if err := s.Codec.WriteULEB128(client.Conn, rpc.NewPingResp()); err != nil {
client.Close()
}
client.UpdateLastPingTime()
case rpc.PongMsg:
case rpc.ReqMsg, rpc.PushMsg:
req := &rpc.Req{}
req.FromGJson(msg)
if req.Param == nil {
return
}
resp := s.Handler.HandleReq(client, req)
// Requests that do not require a reply will not be processed if the response is obtained.
if resp == nil {
return
}
// Determine whether it is an error response message
if _, ok := msg.GetString("e"); ok {
client.Close() // Wrong response information, actively close the connection
return
}
if _, ok := msg.GetString("ec"); ok {
client.Close() // Wrong response information, actively close the connection
return
}
if err := s.Codec.WriteULEB128(client.Conn, resp); err != nil {
client.Close()
}
case rpc.RespMsg:
resp := &rpc.Resp{}
resp.FromGJson(msg)
s.Handler.HandleResp(client, resp)
default:
xlog.Ins.Error(s.Handler.Name(), zap.Error(fmt.Errorf("Unknown message type: %d", msgType)))
}
}
_ = s.pool.Submit(task)
return
}
🤖 Non-English text detected, translating...
https://github.com/panjf2000/gnet/blob/1.x/eventloop_unix.go#L125-L126
Oh, I understand
Actions I've taken before I'm here
Questions with details
netpoll v1版本默认是水平触发,V2版本默认是边缘触发吗?
Code snippets (optional)
No response