介绍
小编给大家分享一下走语言怎么手动处理TCP粘包,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获、下面让我们一起去了解一下吧!
<强>前言强>
一般所谓的TCP粘包是在一次接收数据不能完全地体现一个完整的消息数据.TCP通讯为何存在粘包呢?主要原因是TCP是以流的方式来处理数据,再加上网络上MTU的往往小于在应用处理的消息数据,所以就会引发一次接收的数据无法满足消息的需要,导致粘包的存在。处理粘包的唯一方法就是制定应用层的数据通讯协议,通过协议来规范现有接收的数据是否满足消息数据的需要。在应用中处理粘包的基础方法主要有两种分别是以4节字描述消息大小或以结束符,实际上也有两者相结合的如HTTP、复述的通讯协议等。
<强>应用场景强>
大部分TCP通讯场景下,使用自定义通讯协议
<强>粘包处理原理:通过请求头中数据包大小,将客户端N次发送的数据缓冲到一个数据包中强>
例如:
请求头占3个字节(指令头1字节,数据包长度2字节),版本占1个字节,指令占2个字节
协议规定一个数据包最大是512字节,请求头中数据包记录是1300字节,完整的数据包是1307个字节,此时服务器端需要将客户端3次发送数据进行粘包处理
<强>代码示例强>
package 服务器 import ( ,“net" ,“bufio" ,“ftj-data-synchro/protocol" ,“;golang.org/x/text/transform" ,“;golang.org/x/text/encoding/simplifiedchinese" ,“io/ioutil" ,“bytes" ,“ftj-data-synchro/logic" ,“fmt" ,“strconv" )/* ,客户端结构体 ,*/type Client  struct { ,DeviceID string //客户端连接的唯标志 ,Conn net.Conn ,//连接 ,reader * bufio.Reader //读取 ,writer * bufio.Writer //输出 ,Data [] byte ,//接收数据 } func NewClient (conn * net.TCPConn), * Client { ,reader :=, bufio.NewReaderSize(康涅狄格州,10240) ,writer :=, bufio.NewWriter(康涅狄格州) ,c :=,,客户{康涅狄格州:康涅狄格州,读者:读者,作者:作家} return c }/* * ,数据读取(粘包处理) ,*/func (却;能够*客户)阅读(),{ ,for { var 才能;data []字节 var 才能;err 错误//读才能取指令头,返回输入流的前4个字节,不会移动读取位置 数据,才能,err =, this.reader.Peek (4) if 才能len(数据),==,0,| |,err !=, nil { ,才能继续 ,,}//才能返回缓冲中现有的可读取的字节数 var 才能;byteSize =, this.reader.Buffered () fmt.Printf才能(“读取字节长度:% d \ n",, byteSize)//生才能成一个字节数组,大小为缓冲中可读字节数 data =,才能使([]字节,,byteSize)//读才能取缓冲中的数据 this.reader.Read才能(数据) fmt.Printf才能(“读取字节:% d \ n",,数据)//保才能存到新的缓冲区 for 才能,_,v :=, range data { ,,this.Data =,附加(this.Data, v) ,,} if 才能len (this.Data), & lt;, 4, { ,,//数据包缓冲区清空 ,,this.Data =,[]字节{} ,,fmt.Printf(“非法数据,无指令头…\ n") ,才能继续 ,,} 数据,才能,err =, protocol.HexBytesToBytes (this.Data [4]) instructHead,才能,_ :=, strconv.ParseUint(字符串(数据),16日,16)//指才能令头效验 if 才能uint16 (instructHead), !=, 42330, { ,,fmt.Printf(“非法数据\ n") ,,//数据包缓冲区清空 ,,this.Data =,[]字节{} ,才能继续 ,,} 时间=data 才能;this.Data [: protocol.HEADER_SIZE] var 才能;p =, protocol.Decode(数据) fmt.Printf才能(“消息体长度:% d \ n",, p.Len) var 才能;bodyLength =, len (this.Data),, ,/* * ,,判断数据包缓冲区的大小是否小于协议请求头中数据包大小 ,,如果小于,等待读取下一个客户端数据包,否则对数据包解码进行业务逻辑处理 ,,*/if 才能,int (p.Len),祝辞,len (this.Data),安康;protocol.HEADER_SIZE { ,,fmt.Printf(“身体体长度:% d,读取的身体体长度:% d \ n",, p.Len,, bodyLength) ,才能继续 ,,} fmt.Printf才能(“实际处理字节:% v \ n",, this.Data) 时间=p 才能;protocol.Decode (this.Data)//才能逻辑处理 go 才能this.logicHandler (p)//才能数据包缓冲区清空 时间=this.Data 才能;[]字节{} ,} }去语言怎么手动处理TCP粘包