理解成一个TCP连接就是两根相反流动的水管,水就是其中的数据,
数据是没有边界的,水流也没有界限,因此你需要根据水流的大小,来截取对应的数据,解码成你需要的数据。
比如协议规定tcp 的头部2个字节表示长度,余下的字节表示body部分的具体内容(具体协议可以自定义)
于是我在第一次读取数据的时候,先读取2个字节,然后把这两个字节转成10进制,就是body的长度. 然后重新生成body的数组,继续读:
var conn net.Conn
type YourStruct struct {
Username string `json:"username"`
}
for {
b := make([]byte, 2)
_, err := io.ReadFull(conn, b)
if err != nil {
return
}
length := binary.BigEndian.Uint16(b)
body := make([]byte, length)
_, err = io.ReadFull(conn, body)
if err != nil {
return
}
// 解析结构体
var v = new(YourStruct)
json.Unmarshal(body, v)
fmt.Println(v.Username)
}
写数据也是一样的道理:
- 先计算需要写的长度,转换成byte数组发送,然后再发送body。
var conn net.Conn
type YourStruct struct {
Username string `json:"username"`
}
for {
v := YourStruct{Username: "hahah"}
data, _ := json.Marshal(v)
header := make([]byte, 2)
binary.BigEndian.PutUint16(header, uint16(len(data)))
// 写头
conn.Write(header)
// 写body
conn.Write(data)
}
tcp的边界定义就是跟据你定的协议,组装好数据包,发送的时候组装包,获取的时候拆包.
2个字节的头,body最长应该是65535个字节,超过这个长度,header就应该增加长度
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…