Skip to content
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

[Question]: Is the netpoll v1 version defaulting to horizontal triggering, and the V2 version defaulting to edge triggering? #575

Closed
3 tasks done
chen2ding opened this issue Apr 15, 2024 · 15 comments
Labels
help wanted Extra attention is needed question Further information is requested

Comments

@chen2ding
Copy link

Actions I've taken before I'm here

  • I've thoroughly read the documentations about this problem but still have no answer.
  • I've searched the Github Issues/Discussions but didn't find any similar problems that have been solved.
  • I've searched the internet for this problem but didn't find anything helpful.

Questions with details

netpoll v1版本默认是水平触发,V2版本默认是边缘触发吗?

Code snippets (optional)

No response

@chen2ding chen2ding added help wanted Extra attention is needed question Further information is requested labels Apr 15, 2024
@gh-translator gh-translator changed the title [Question]: netpoll v1版本默认是水平触发,V2版本默认是边缘触发吗 [Question]: Is the netpoll v1 version defaulting to horizontal triggering, and the V2 version defaulting to edge triggering? Apr 15, 2024
@panjf2000
Copy link
Owner

See #573

@chen2ding
Copy link
Author

chen2ding commented Apr 15, 2024

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
}

@gh-translator
Copy link
Collaborator

🤖 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
}

@chen2ding
Copy link
Author

@panjf2000 请问这是什么问题呢

@gh-translator
Copy link
Collaborator

🤖 Non-English text detected, translating...


@panjf2000 What is the problem?

@chen2ding
Copy link
Author

@panjf2000 调试感觉是buf中的数据我没有读完,然后后面就不触发OnTraffic了,v1版本正常的

@gh-translator
Copy link
Collaborator

🤖 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.

@panjf2000
Copy link
Owner

First format your code, it's unreadable.

@chen2ding
Copy link
Author

@panjf2000 已经格式化了,麻烦看下上面代码呢

@gh-translator
Copy link
Collaborator

🤖 Non-English text detected, translating...


@panjf2000 It has been formatted. Please take a look at the above code.

@panjf2000
Copy link
Owner

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.

@gh-translator
Copy link
Collaborator

🤖 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 calling OnTraffic again until new data arrives on the socket. I think the root cause of your problem is that gnetv1 internally loops reading and decoding packets, while gnetv2 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
}

@panjf2000
Copy link
Owner

@chen2ding
Copy link
Author

@gh-translator
Copy link
Collaborator

🤖 Non-English text detected, translating...


https://github.com/panjf2000/gnet/blob/1.x/eventloop_unix.go#L125-L126

Oh, I understand

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants