-
Notifications
You must be signed in to change notification settings - Fork 383
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
link程序 , 复杂包头, 如何进行拆包? #35
Comments
你好。 如果用funny/binary包当中的binary.Reader和binary.Writer的分包机制,只能做简单的消息分包,无法提取包头信息。 所以,对于你说的这种需要提取包头信息的情况,应该自己实现一个link.Codec来做消息解析。 |
你好,达达 |
包头和包体内容同时提取的确是一些协议设计中会出现,但是协议太过具体,没办法放到link里面。 link能提供的只有机制,Codec机制足够抽象,所以可以用来实现这样类型的协议,实施起来应该不复杂。 我这里友情赠送演示代码一份,请针对具体需求再自行改造: package link
import (
"github.com/funny/binary"
"io"
)
type YarMessage struct {
Id uint32
Version uint16
MagicNum uint32
Provider [32]byte
Token [32]byte
Message interface{}
}
type YarCodecType struct {
CodecType CodecType
}
func Yar(codecType CodecType) YarCodecType {
return YarCodecType{codecType}
}
func (codecType YarCodecType) NewCodec(r io.Reader, w io.Writer) Codec {
br := binary.NewReader(r)
bw := binary.NewWriter(w)
pr := binary.NewPacketReader(binary.SplitByUint32BE, br)
pw := binary.NewPacketWriter(binary.SplitByUint32BE, bw)
return &YarCodec{
codec: codecType.CodecType.NewCodec(pr, pw),
reader: br,
writer: bw,
pwriter: pw,
}
}
type YarCodec struct {
codec Codec
reader *binary.Reader
writer *binary.Writer
pwriter *binary.PacketWriter
}
func (codec *YarCodec) Decode(msg interface{}) error {
ym := msg.(*YarMessage)
ym.Id = codec.reader.ReadUint32BE()
ym.Version = codec.reader.ReadUint16BE()
ym.MagicNum = codec.reader.ReadUint32BE()
_ = codec.reader.ReadUint32BE()
codec.reader.ReadFull(ym.Provider[:])
codec.reader.ReadFull(ym.Token[:])
return codec.codec.Decode(ym.Message)
}
func (codec *YarCodec) Encode(msg interface{}) error {
ym := msg.(*YarMessage)
codec.writer.WriteUint32BE(ym.Id)
codec.writer.WriteUint16BE(ym.Version)
codec.writer.WriteUint32BE(ym.MagicNum)
codec.writer.WriteUint32BE(0)
codec.writer.Write(ym.Provider[:])
codec.writer.Write(ym.Token[:])
if err := codec.codec.Encode(ym.Message); err != nil {
return err
}
return codec.pwriter.Flush()
} 已通过单元测试: func Test_Yar(t *testing.T) {
SessionTest(t, Bufio(Yar(Json())), func(t *testing.T, session *Session) {
for i := 0; i < 2000; i++ {
msg1 := RandObject()
msg2 := &YarMessage{Message: &msg1}
copy(msg2.Provider[:], RandBytes(32))
copy(msg2.Token[:], RandBytes(32))
err := session.Send(msg2)
unitest.NotError(t, err)
var msg3 TestObject
msg4 := &YarMessage{Message: &msg3}
err = session.Receive(msg4)
unitest.NotError(t, err)
unitest.Pass(t, msg2.Provider == msg4.Provider)
unitest.Pass(t, msg2.Token == msg4.Token)
unitest.Pass(t, msg1 == msg3)
}
})
} 前后差不多花了半个多小时,开发起来还算是比较高效的。 |
解包还需要考虑粘包的情况吧?这个应该自己逻辑处理就可以了,提供机制就好了,类似Netty那样。 |
@LaoZhongGu 上面的代码已经包含了消息分包逻辑在里面 |
谢谢 达达大神。 清楚每个项目包头都不一样。 |
|
没删,看api.go里面的接口声明,有些变动 |
达达大神, 网络收包的粘包问题有没有提供机制处理? |
例如包头:
The text was updated successfully, but these errors were encountered: