IT评测·应用市场-qidao123.com

标题: GolangTCP通信办理粘包问题 [打印本页]

作者: 河曲智叟    时间: 2025-3-15 02:35
标题: GolangTCP通信办理粘包问题
重要原因就是tcp数据传递模式是流模式,在保持长毗连的时间可以举行多次的收和发。
“粘包"可发生在发送端也可发生在接收端:
     办理办法

出现"粘包"的关键在于接收方不确定将要传输的数据包的大小,因此我们可以对数据包举行封包和拆包的操纵。
封包:封包就是给一段数据加上包头,如许一来数据包就分为包头和包体两部门内容了(过滤非法包时封包会参加"包尾"内容)。包头部门的长度是固定的,并且它存储了包体的长度,根据包头长度固定以及包头中含有包体长度的变量就能正确的拆分出一个完备的数据包。
我们可以自己定义一个协议,好比数据包的前4个字节为包头,里面存储的是发送的数据的长度。
protocol包:
  1. package protocol
  2. import (
  3.         "bufio"
  4.         "bytes"
  5.         "encoding/binary"
  6. )
  7. // Encode 将消息编码
  8. func Encode(message string) ([]byte, error) {
  9.         // 读取消息的长度,转换成int32类型(占4个字节)
  10.         var length = int32(len(message))
  11.         var pkg = new(bytes.Buffer)
  12.         // 写入消息头
  13.         err := binary.Write(pkg, binary.LittleEndian, length)
  14.         if err != nil {
  15.                 return nil, err
  16.         }
  17.         // 写入消息实体
  18.         err = binary.Write(pkg, binary.LittleEndian, []byte(message))
  19.         if err != nil {
  20.                 return nil, err
  21.         }
  22.         return pkg.Bytes(), nil
  23. }
  24. // Decode 解码消息
  25. func Decode(reader *bufio.Reader) (string, error) {
  26.         // 读取消息的长度
  27.         lengthByte, _ := reader.Peek(4) // 读取前4个字节的数据
  28.         lengthBuff := bytes.NewBuffer(lengthByte)
  29.         var length int32
  30.         err := binary.Read(lengthBuff, binary.LittleEndian, &length)
  31.         if err != nil {
  32.                 return "", err
  33.         }
  34.         // Buffered返回缓冲中现有的可读取的字节数。
  35.         if int32(reader.Buffered()) < length+4 {
  36.                 return "", err
  37.         }
  38.         // 读取真正的消息数据
  39.         pack := make([]byte, int(4+length))
  40.         _, err = reader.Read(pack)
  41.         if err != nil {
  42.                 return "", err
  43.         }
  44.         return string(pack[4:]), nil
  45. }
复制代码

客户端:
  1. func main() {
  2.         conn, err := net.Dial("tcp", "127.0.0.1:30000")
  3.         if err != nil {
  4.                 fmt.Println("dial failed, err", err)
  5.                 return
  6.         }
  7.         defer conn.Close()
  8.         for i := 0; i < 20; i++ {
  9.                 msg := `Hello, Hello. How are you?`
  10.                 data, err := proto.Encode(msg)
  11.                 if err != nil {
  12.                         fmt.Println("encode msg failed, err:", err)
  13.                         return
  14.                 }
  15.                 conn.Write(data)
  16.         }
  17. }
复制代码
服务器:
  1. package main
  2. import (
  3.         "bufio"
  4.         "fmt"
  5.         "io"
  6.         "net"
  7.         proto "studygo/studygo/tcp/protocol"
  8.         "sync"
  9. )
  10. var wg sync.WaitGroup
  11. func process(conn net.Conn) {
  12.         //与客户端通信
  13.         defer conn.Close()
  14.         reader := bufio.NewReader(conn)
  15.         for {
  16.                 msg, err := proto.Decode(reader)
  17.                 if err == io.EOF {
  18.                         break
  19.                 }
  20.                 if err!=nil{
  21.                         fmt.Println("decode msg failed,err:",err)
  22.                         return
  23.                 }
  24.                 fmt.Println(msg)
  25.         }
  26. }
  27. func main() {
  28.         //本地端口启动服务
  29.         listener, err := net.Listen("tcp", "127.0.0.1:8000")
  30.         if err != nil {
  31.                 fmt.Println("listen failed,err:%v\n", err)
  32.                 return
  33.         }
  34.         defer listener.Close()
  35.         for {
  36.                 //等待别人连接
  37.                 conn, err := listener.Accept()
  38.                 if err != nil {
  39.                         fmt.Println("accept failed,err:%v\n", err)
  40.                         return
  41.                 }
  42.                 go process(conn)
  43.         }
  44. }
复制代码
参考出处:Go语言基础之网络编程 | 李文周的博客

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4