3、Netty·粘包拆包
2021-05-18 16:38:01 18 举报
通过自定义消息协议,自定义消息协议的编解码器来解决客户端和服务端通信时,有可能出现的tcp数据拆包和粘包问题
作者其他创作
大纲/内容
D1
m1
1、使用自定义协议+编解码器来解决2、关键就是要解决服务器端每次读取数据长度的问题,这个问题解决了,就不会出现服务器多读或少读数据的问题了,从而避免了TCP粘包和拆包。看一个具体的实例:1、要求客户端发送5个Message对象,客户端每次发送一个2、服务端每次接收一个Message对象,分5次进行解码,每读取一个Message对象,会回复一个Message对象给客户端
m4
m5
D2_2
D2
D2_1
代码案例(解决方案,重点是自定义消息协议,指定发送的字节长度)
1、TCP是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务端)都要有一一成对的socket,因此,发送端为了将多个发送给接收端的包,更有效的发给对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样做虽然提高了效率,但是接收端就难于分辨出完整的数据包了,因为面向流的通信是无消息保护边界的。2、由于TCP是无消息保护边界,需要在接收端处理消息边界问题,也就是我们所说的粘包、拆包问题
Server
1、自定义消息协议对象(重点)
m2
m3
5、服务端通道处理器
Client
public class MessageProtocol { /**消息的长度(关键)*/ private int len; /**消息的内容*/ private byte[] content; public MessageProtocol(byte[] content) { this.content = content; this.len = content.length; } public int getLen() { return len; } public void setLen(int len) { this.len = len; } public byte[] getContent() { return content; } public void setContent(byte[] content) { this.content = content; }}
2、自定义协议对象的编码器(注意writeInt这个方法)
假设客户端分别发送了两个数据包D1和D2给服务端,由于服务端一次读取到字节数不是确定的,故可能存在以下四种情况:1、服务端分两次读取到两个独立的数据包,分别是D1和D2,没有粘包和拆包2、服务端一次性接收到两个数据包,D1和D2粘合在一起,称之为TCP粘包3、服务端分别两次读取到了数据包,第一次读取到了完整的D1包和D2包的一部分,第二次读取到了D2包的剩余部分,这称之为TCP拆包4、服务端分别两次读取到了数据包,第一次读取到了D1包的部分内容,第二次读取到了D1包的剩余内容和完整的D2数据包,这称之为拆包
D1_2
4、客户端通道处理器
3、自定义协议对象的解码器(注意len这个地方)
D1_1
0 条评论
回复 删除
下一页