Golang 开发 Socket 通信时常用的 TCP 封包和解包协议

在开发 Socket 通信时,由于 TCP 协议的特性,在网络状况不佳的情况下,数据传输过程中经常会出现半包或粘包。为解决这一问题,通常我们需要自定义一个通信协议,增加一个 HEADER 部分,并在其中对数据包的长度进行声明,下面分享一段封包和解包的示例代码,可用于 Golang 开发 Socket 时处理数据传输,具体代码如下:

package protocol
 
import (
    "bytes"
    "encoding/binary"
)
 
const (
    TCP_HEADER     = "TCPHEADER"
    TCP_HEADER_LEN = 9
    TCP_DATA_LEN   = 4
)
 
// 封包
func Enpack(msg []byte) []byte {
    return append(append([]byte(TCP_HEADER), IntToBytes(len(msg))...), msg...)
}
 
// 解包
func Depack(buffer []byte, readerChannel chan []byte) []byte {
    length := len(buffer)
 
    var i int
    for i = 0; i < length; i++ {
        if length < i + TCP_HEADER_LEN + TCP_DATA_LEN {
            break
        }
        if string(buffer[i:i + TCP_HEADER_LEN]) == TCP_HEADER {
            msgLen := BytesToInt(buffer[i + TCP_HEADER_LEN : i + TCP_HEADER_LEN + TCP_DATA_LEN])
            if length < i + TCP_HEADER_LEN + TCP_DATA_LEN + msgLen {
                break
            }
            data := buffer[i + TCP_HEADER_LEN + TCP_DATA_LEN : i + TCP_HEADER_LEN + TCP_DATA_LEN + msgLen]
            readerChannel <- data
 
            i += TCP_HEADER_LEN + TCP_DATA_LEN + msgLen - 1
        }
    }
 
    if i == length {
        return make([]byte, 0)
    }
    
    return buffer[i:]
}
 
// 整形转换成字节
func IntToBytes(n int) []byte {
	x := int32(n)
    bytesBuffer := bytes.NewBuffer([]byte{})
    binary.Write(bytesBuffer, binary.BigEndian, x)
    
    return bytesBuffer.Bytes()
}
 
// 字节转换成整形
func BytesToInt(b []byte) int {
    bytesBuffer := bytes.NewBuffer(b)
    var x int32
    binary.Read(bytesBuffer, binary.BigEndian, &x)
    
    return int(x)
}

 

相关内容:

发表评论