gnet-io / gnet-examples

Examples of gnet
MIT License
245 stars 77 forks source link

升级gnet版本为v1.6.3 出现问题 #11

Closed zcx1218029121 closed 2 years ago

zcx1218029121 commented 2 years ago

win环境下 1.自定义解码器 如果async==true 会出现调用两次encode的情况

2021/12/21 16:34:47 receive , &{32769 240 13 [128 1 0 240 0 0 0 5 104 101 108 108 111]}, data:� �   hello
2021/12/21 16:34:47 receive , &{32769 240 13 [128 1 0 240 0 0 0 5 119 111 114 108 100]}, data:� �   world

liunx环境下

  1. gnet.WithTCPKeepAlive(time.Minute*5) 似乎无效 发送一次就断开连接
  2. 关闭服务器程序后依然占用端口 大概2分钟左右解除占用
zcx1218029121 commented 2 years ago

custom_codec 两个问题都是在 custom_codec 包下面的出现的 如果不配置自定义解码器 似乎不会出现收到一次报文就结束的情况

panjf2000 commented 2 years ago

custom codec 那个例子可能有问题,你自己写 codec 有这种问题吗?

zcx1218029121 commented 2 years ago

照着实现了一个custom codec,发现这个问题后发现和例子的gnet版本不一样。尝试升级示例程序的gnet版本后复现了。 现在把我自己写的版本的gnet版本降级为v1.2.4后也没出现这个问题了。

codec代码如下

package g698

import (
    "bytes"
    "encoding/binary"
    "errors"
    "g698/util"
    "github.com/panjf2000/gnet"
)

type Pd struct {
}

//拆包器
func (sf *Pd) Encode(c gnet.Conn, buf []byte) ([]byte, error) {
    var err error
    result := make([]byte, 0)
    buffer := bytes.NewBuffer(result)
    if len(buf) > 0 {
        err = buffer.WriteByte(Start)
        if err != nil {
            return nil, errors.New("start")
        }
        _, err = buffer.Write(buf)
        if err != nil {
            return nil, errors.New("payload")
        }
        err = buffer.WriteByte(End)
        if err != nil {
            return nil, errors.New("end")
        }
    }

    return buffer.Bytes(), err
}

//Decode gnet 拆包器 负责校验 魔术头和crc
func (sf *Pd) Decode(c gnet.Conn) ([]byte, error) {

    //先读到 长度
    if size, header := c.ReadN(3); size == 3 {
        //获取start
        bf := bytes.NewBuffer(header)
        var start byte
        _ = util.Read(bf, &start)
        if start != Start {
            c.ResetBuffer()
            return nil, errors.New("起始符校验错误")
        }
        //获得Len
        var rawLen uint16
        _ = binary.Read(bf, binary.LittleEndian, &rawLen)
        dataLen:=GetFrameLen(rawLen)
        protocolLen := int(dataLen) + 2
        if dataSize, s := c.ReadN(protocolLen); dataSize == protocolLen {
            //拆包
            c.ShiftN(protocolLen)
            return s[3:protocolLen], nil
        }

    }

    return nil, errors.New("not enough len data")
}
func GetFrameLen(rawLen uint16) (FrameLen uint16) {
    if rawLen&(1<<14) > 0 {
        rawLen &= 0x3fff
        FrameLen = rawLen * 1000
    }
    FrameLen = rawLen & 0x3fff
    return
}
panjf2000 commented 2 years ago

你说的问题是指?windows 那个是已知问题,最新代码修复了,linux 下还有什么问题?

zcx1218029121 commented 2 years ago

好的我升级一下版本试一下