背景
TCP 是以流的方式来处理数据,一个完整的包可能会被 TCP 拆分成多个包进行发送,也可把小的封装成一个大的数据包发送。
应用程序写入的字节大小大于套接字发送缓冲区的大小,会发生拆包现象
应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包现象;
常见的解决方法
- 客户端在发送数据包的时候,每个包都固定长度,比如1024个字节大小,如果客户端发送的数据长度不足1024个字节,则通过补充空格的方式补全到指定长度;
- 客户端编码的时候在每个包的末尾使用固定的分隔符,例如\r\n,服务端解码的时候遇到约定的分隔符才算一个完整的包;
- 将消息分为头部和消息体,在头部中保存有当前整个消息的长度,只有在读取到足够长度的消息之后才算是读到了一个完整的消息;
- 通过自定义协议进行粘包和拆包的处理。即可以自行约定编码解码的格式
Netty提供的编码解码
FixedLengthFrameDecoder
对于使用固定长度的粘包和拆包场景,可以使用FixedLengthFrameDecoder,该解码一器会每次读取固定长度的消息,如果当前读取到的消息不足指定长度,那么就会等待下一个消息到达后进行补足。
LineBasedFrameDecoder与DelimiterBasedFrameDecoder
对于通过分隔符进行粘包和拆包问题的处理
LineBasedFrameDecoder的作用主要是通过换行符,即\n或者\r\n对数据进行处理;
DelimiterBasedFrameDecoder的作用则是通过用户指定的分隔符对数据进行粘包和拆包处理。
LengthFieldBasedFrameDecoder与LengthFieldPrepender
LengthFieldBasedFrameDecoder与LengthFieldPrepender需要配合起来使用,其实本质上来讲,这两者一个是解码,一个是编码
它们处理粘拆包的主要思想是在生成的数据包中添加一个长度字段,用于记录当前数据包的长度。
LengthFieldBasedFrameDecoder会按照参数指定的包长度偏移量数据对接收到的数据进行解码,从而得到目标消息体数据;
LengthFieldPrepender则会在响应的数据前面添加指定的字节数据,这个字节数据中保存了当前消息体的整体字节数据长度。
网友评论