go语言 TCP粘包问题处理
package main
import (
"bytes"
"encoding/binary"
"encoding/json"
"fmt"
"log"
"net"
)
const BUF_SIZE = 1024
const HEAD_SIZE = 50
type Header struct {
DataLength int `json:"data_length"`
Fill string `json:"fill"`
}
func PackMsgHeader(header *Header) {
marshaled, _ := json.Marshal(header)
fillUpSize := HEAD_SIZE - len(marshaled)
fillStr := ""
for i := 0; i < fillUpSize; i++ {
fillStr += "0"
}
header.Fill = fillStr
}
func doConn(conn net.Conn) {
var (
buffer = bytes.NewBuffer(make([]byte, 0, BUF_SIZE)) //buffer用来缓存读取到的数据
readBytes = make([]byte, BUF_SIZE) //readBytes用来接收每次读取的数据,每次读取完成之后将readBytes添加到buffer中
isHead = true //用来标识当前的状态:正在处理size部分还是body部分
bodyLen = 0 //表示body的长度
)
for {
//首先读取数据
readByteNum, err := conn.Read(readBytes)
if err != nil {
log.Fatal(err)
return
}
buffer.Write(readBytes[0:readByteNum]) //将读取到的数据放到buffer中
// 然后处理数据
for {
if isHead {
if buffer.Len() >= HEAD_SIZE {
isHead = false
head := make([]byte, HEAD_SIZE)
_, err = buffer.Read(head)
if err != nil {
log.Fatal(err)
return
}
header := &Header{}
json.Unmarshal(head, &header)
bodyLen = header.DataLength
} else {
break
}
}
if !isHead {
if buffer.Len() >= bodyLen {
body := make([]byte, bodyLen)
_, err = buffer.Read(body[:bodyLen])
if err != nil {
log.Fatal(err)
return
}
fmt.Println("received body: " + string(body[:bodyLen]))
isHead = true
} else {
break
}
}
}
}
}
func Test_tcp_serve1() {
listener, err := net.Listen("tcp", "127.0.0.1:1234")
if err != nil {
log.Fatal(err)
return
}
log.Println("start listening on 1234")
for {
conn, err := listener.Accept()
if err != nil {
log.Fatal(err)
return
}
go doConn(conn)
}
}
func SendStringwithTcp(arg string) error {
conn, err := net.Dial("tcp", ":1234")
if err != nil {
log.Fatal(err)
return err
}
head := make([]byte, HEAD_SIZE)
content := []byte(arg)
headSize := len(content)
binary.BigEndian.PutUint16(head, uint16(headSize))
//先写入head部分,再写入body部分
_, err = conn.Write(head)
if err != nil {
log.Fatal(err)
return err
}
_, err = conn.Write(content)
if err != nil {
log.Fatal(err)
return err
}
return nil
}
func Test_tcp_cli1() {
conn, _ := net.Dial("tcp", "127.0.0.1:1234")
msg := "YFR718sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
for i := 0; i < 200; i++ {
content := []byte(msg)
contentSize := len(content)
header := &Header{
DataLength: contentSize,
Fill: "",
}
PackMsgHeader(header)
headerMarshaled, _ := json.Marshal(header)
//先写入head部分,再写入body部分
conn.Write(headerMarshaled)
conn.Write(content)
}
}
func main() {
go func() {
Test_tcp_serve1()
}()
go func() {
Test_tcp_cli1()
}()
time.Sleep(1 * time.Hour)
}

版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。
转载请注明来源:go语言 TCP粘包问题处理 - 多知在线