基于TCP服务的TLV编解码
一、实现思路
- 实现一个tcp服务端和tcp客户端
- 通过TLV方式编解码
TLV分别为:标签域(Tag),长度域(Length),内容域(Value)。
二、实现代码
service_test.go
package serverimport ("errors""fmt""github.com/sea-project/sea-pkg/util/conv""io""net""testing"
)const (TypeLen = 1 // 2^8=256LenLen = 2 // 2^16=65536ContentMaxLen = 1024 * 64BufLen = 1 + 2 + 1024*64MsgText = uint8(66) // 文字信息MsgImg = uint8(88) // 图片信息
)func Test_TLVMain(t *testing.T) {listener, _ := net.Listen("tcp", "127.0.0.1:8888")for {conn, err := listener.Accept()if err != nil {fmt.Println(err)continue}fmt.Println("A client connected :" + conn.RemoteAddr().String())go tcpPipe(conn)}
}func tcpPipe(conn net.Conn) {bufData := make([]byte, BufLen)var err errorvar data []bytefor {_, _ = io.ReadFull(conn, bufData)if len(bufData) == 0 {break}data, bufData, err = Unpack(bufData)if err != nil {conn.Close()}if len(data) == 0 {break}var msgType stringif uint8(data[:1][0]) == 66 {msgType = "文字消息:"} else {msgType = "图片消息:"}fmt.Println(msgType + string(data[1:]))}
}func Unpack(buf []byte) ([]byte, []byte, error) {// 取出消息类型t := uint8(buf[:1][0])if t != 66 && t != 88 {err := errors.New("消息类型错误")return nil, nil, err}// 取出消息长度l := conv.Bytes2uint16(buf[1:3])data := buf[0 : l+3]bufData := buf[l+3:]return data, bufData, nil
}
client_test.go
package clientimport ("bytes""encoding/binary""github.com/sea-project/sea-pkg/util/time""net""testing"
)const (TypeLen = 1 // 2^8=256LenLen = 2 // 2^16=65536ContentMaxLen = 1024 * 64BufLen = 1 + 2 + 1024*64MsgText = uint8(66) // 文字信息MsgImg = uint8(88) // 图片信息
)func Test_TLVMain2(t *testing.T) {conn, _ := net.Dial("tcp", "127.0.0.1:8888")for i := 0; i < 100; i++ {currTime := time.GetUnixToFormatString(time.CurrentSecond(), "2006-01-02 15:04:05")data := []byte(currTime + " Hello World! \n")data = Pack(data)conn.Write(data)}}func Pack(msg []byte) []byte {var t uint8var l uint16if time.CurrentMilliSecond()%2 == 0 {t = 66} else {t = 88}l = uint16(len(msg))dataBuff := bytes.NewBuffer([]byte{})if err := binary.Write(dataBuff, binary.BigEndian, t); err != nil {return nil}if err := binary.Write(dataBuff, binary.BigEndian, l); err != nil {return nil}if err := binary.Write(dataBuff, binary.BigEndian, msg); err != nil {return nil}return dataBuff.Bytes()
}