1 为什么会出现粘包

主要原因是tcp 数据传递模式是留模式,在长连接过程中可以进行多次收发。数据粘包可以发生在客户端和服务端。

2 解决办法

出现粘包的关键在于不确定包的大小,因此可以通过封包将把的内容长度封装在包头,用固定长度的值来存储包内容长度。自己封装一个数据传输协议。如下:

package protoimport ("bufio""bytes""encoding/binary"
)// Encode 将消息编码
func Encode(message string) ([]byte, error) {var length = int32(len(message)) // 读取消息的长度,转换成int32类型(占4个字节)var pkg = new(bytes.Buffer) // 定义一个空的bytes 缓冲区// 写入消息头err := binary.Write(pkg, binary.LittleEndian, length) //通过小端序列的方式把length 写到pkg。binary.LittleEndian 为编码格式if err != nil {return nil, err}// 写入消息实体err = binary.Write(pkg, binary.LittleEndian, []byte(message)) //在通过小端序列的方式把真实的包内容写入bytes,封装成一个包。if err != nil {return nil, err}return pkg.Bytes(), nil // 返回封装好的包
}// Decode 解码消息
func Decode(reader *bufio.Reader) (string, error) {lengthByte, _ := reader.Peek(4) // 读取前4个字节的数据,及包的内容长度,endoce 里面的length。Peek的方式读取内容,是不会清掉缓存的lengthBuff := bytes.NewBuffer(lengthByte) //定义一个以lengthByte为内容的bytes缓冲区var length int32err := binary.Read(lengthBuff, binary.LittleEndian, &length)// 将lengthBuff 的内容写到length里面。这里要相应解码才能读取到length的内容if err != nil {return "", err}// Buffered返回缓冲中现有的可读取的字节数。前面用Peek读取,所以这里数据内容应该大于length+4if int32(reader.Buffered()) < length+4 {return "", err}// 读取真正的消息数据pack := make([]byte, int(4+length)) // 创建字节切片_, err = reader.Read(pack) if err != nil {return "", err}return string(pack[4:]), nil //返回去掉length的字符串
}

后续在客户端发送消息的时候编码,读写的时候解码就行了

// 客户端
msg := `Hello, Hello. How are you?`
data, err := proto.Encode(msg)
conn.Write(data)
//服务端
msg, err := proto.Decode(reader)
if err == io.EOF {return
}
if err != nil {fmt.Println("decode msg failed, err:", err)return
}

go TCP 粘包原理和解决方案相关推荐

  1. Socket编程(4)TCP粘包问题及解决方案

    ① TCP是个流协议,它存在粘包问题 TCP是一个基于字节流的传输服务,"流"意味着TCP所传输的数据是没有边界的.这不同于UDP提供基于消息的传输服务,其传输的数据是有边界的.T ...

  2. TCP粘包|拆包和解决方案

    1 产生原因 TCP是面向连接的,面向流的,提供高可靠性服务.收发两端(客户端和服务端)都要有一一成对的socket,因此,发送端为了将多个发给接收端的包,更有效的发给对方,使用了优化算法(Nagle ...

  3. TCP粘包问题的解决方案01——自定义包体

    粘包问题:应用层要发送数据,需要调用write函数将数据发送到套接口发送缓冲区.如果应用层数据大小大于SO_SNDBUF,那么,可能产生这样一种情况,应用层的数据一部分已经被发送了,还有一部分还在套接 ...

  4. Socket编程 TCP粘包问题及解决方案

    ① TCP是个流协议,它存在粘包问题 TCP是一个基于字节流的传输服务,"流"意味着TCP所传输的数据是没有边界的.这不同于UDP提供基于消息的传输服务,其传输的数据是有边界的.T ...

  5. TCP 粘包和拆包及解决方案

    TCP 粘包和拆包基本介绍 1.TCP 是面向连接的,面向流的,提供高可靠性服务.收发两端(客户端和服务器端)都要有一一成对的 socket,因此,发送端为了将多个发给接收端的包,更有效的发给对方,使 ...

  6. 20-Netty TCP 粘包和拆包及解决方案

    TCP粘包和拆包的基本介绍 TCP是面向连接的, 面向流的, 提供可靠性服务, 收发两端(客户端和服务器端) 都有一一成对的Socket,因此发送端为了将多个发给接收端的包, 更有效的发给对方, 使用 ...

  7. netty编解码器注意事项及粘包和拆包解决方案

    netty编解码器 当 Netty 发送或者接受一个消息的时候,就将会发生一次数据转换.入站消息会被解码:从字节转换为另一种格式(比如 java 对象):如果是出站消息,它会被编码成字节. Netty ...

  8. TCP粘包、半包原理及解决方案

    引言:TCP协议是网络通信协议中十分重要的协议,相比于UDP协议来说,它是一个可靠的传输协议,并且是一个面向数据流的协议:所谓面向数据流,其实是指数据传输是以流式的方式传输,这些传输的数据就像一条河里 ...

  9. Netty框架之TCP粘包/半包解决方案

    Netty框架之TCP粘包/半包解决方案 一.TCP粘包 二.TCP半包 三.TCP粘包/半包解决方案 1.FixedLengthFrameDecoder定长解析器 2.LineBasedFrameD ...

  10. Netty4实战 - TCP粘包拆包解决方案

    Netty4实战 - TCP粘包&拆包解决方案 参考文章: (1)Netty4实战 - TCP粘包&拆包解决方案 (2)https://www.cnblogs.com/hunrry/p ...

最新文章

  1. 更多的结构化命令(第十三章)
  2. 年底了,游戏大作连连
  3. mysql group_concat去重_MySQL group_concat() 函数用法
  4. Android接口一般定义格式,Android开发规范
  5. USB2.0学习笔记连载(一):CY7C68013特性简介
  6. Python 和 egg 文件
  7. python爬虫cookie池搭建_爬虫——cookies池的搭建
  8. matlab中目录的相关操作
  9. steam快速换号工具易语言源码 附成品
  10. flash电脑安装包_flash控件下载特色众多flash控件下载使用评估
  11. 在哪可以找c语言编程的答案,c语言程序设计课后习题答案.doc
  12. [SUCTF 2019]EasyWeb 1
  13. 植被覆盖指数计算教程(ENVI)
  14. 计算机纳入高考作文,高考作文听人家说今年的高考作文是用计算机批 – 手机爱问...
  15. mac pro 系统升级带来的问题
  16. 陈睿提供2009-06-19
  17. Java学习第二十四天
  18. c语言查表法编程流水灯,通过查表法的流水灯汇编程序
  19. unbutu服务器误删文件,Ubuntu误删系统文件修复办法
  20. ETH 2.0新纪元开启,究竟能带来什么?

热门文章

  1. pdca实施的流程图_思维导图丨《高效PDCA工作术》流程图
  2. 许可证加密的WMV文件破解
  3. WordPress主题 LightSNS v1.6.60 强大的社交系统SNS主题(免受权)
  4. mix2线刷开发板救砖_小米MIX2官方原厂系统rom线刷刷机包降级包下载8.10.25版
  5. Unity经验·任意位置的透视问题
  6. MFC基础之字符集,Unicode字符集,多字节字符集
  7. 用php打印出日历_PHP完成一个日历
  8. 在FireFox中使用IE Tab插件
  9. 国家网络信息安全战略三步曲
  10. C++判断是否为一个凹多边形