概述本文介绍什么是 TCP 粘包和拆包现象 , 并通过 Netty 编写详细的案例来重现 TCP 粘包问题 , 最后再通过一个 Netty 的 demo 来解决这个问题 。具体内容如下
- 什么是 TCP 粘包和拆包现象
- 重现 TCP 粘包和拆包现象
- Netty 解决 TCP 粘包和拆包现象带来的问题
- 如果客户端的每次制造的水比较多 , 也就是我们常说的客户端给的包比较大 , TCP这个搬运工就会分多次去搬运
- 如果客户端每次制造的水比较少的话 , TCP可能会等客户端多次生产之后 , 把所有的水一起再运输到另一端
- 对于第一种情况 , TCP 会再客户端先进行拆包 , 在另一端接收的时候 , 需要把多次获取的结果组合在一起 , 变成我们可以理解的信息
- 对于第二种情况 , TCP 会在客户端先进行粘包 , 在另一端接收的时候 , 就必须进行拆包处理 , 因为每次接收的信息 , 可能是另一个远程端多次发送的包 , 被TCP粘在一起的
- 通过在客户端 1 次发送超大数据包给服务器端来重现 TCP 拆包现象
- 通过在客户端分 10 次发送较小的数据包给服务器端来重现 TCP 粘包现象
Netty maven 依赖
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.76.Final</version></dependency>
通过 Netty 重现 TCP 拆包现象- Netty 客户端启动类:NettyClient
package com.ckJAVA.test.client;import io.netty.bootstrap.Bootstrap;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.ChannelPipeline;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NIOSocketChannel;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Component;@Slf4j@Componentpublic class NettyClient {static final String HOST = System.getProperty("host", "127.0.0.1");static final int PORT = Integer.parseInt(System.getProperty("port", "8080"));static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));public static void main(String[] args) throws Exception {// 初始化客户端事件组EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(group)// 初始化通道.channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializer<SocketChannel>() {// 初始化通道处理器@Overridepublic void initChannel(SocketChannel ch) {ChannelPipeline p = ch.pipeline();p.addLast(new NettyClientHandler());}});b.connect(HOST, PORT).addListener(future -> {log.info(String.format("连接服务器端:%s:%s 成功!", HOST, PORT));}).await();} catch (Exception e) {log.error("启动客户端出现异常", e);}}}
- Netty 客户端通道处理类:NettyClientHandler
package com.ckjava.test.client;import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;import lombok.extern.slf4j.Slf4j;import java.nio.charset.StandardCharsets;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicInteger;@Slf4jpublic class NettyClientHandler extends SimpleChannelInboundHandler<ByteBuf> {private final AtomicInteger countRef = new AtomicInteger(0);//客户端读取服务器发送的信息@Overrideprotected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {byte[] buffer = new byte[msg.readableBytes()];msg.readBytes(buffer);String message = new String(buffer, StandardCharsets.UTF_8);log.info(String.format("客户端接收到消息:[%s]", message));log.info(String.format("客户端接收到消息的次数:%s", countRef.accumulateAndGet(1, Integer::sum)));log.info("---------------------------------------------------");}// 重写 channelActive, 当客户端启动的时候 自动发送数据给服务端@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {// 客户端只发送一次 , 但是本次数据量很大// tcp 会将数据拆分成多份后依次进行发送String data = https://www.isolves.com/it/wl/zs/2022-04-24/"ckjava";StringBuilder stringBuilder = new StringBuilder(data);for (int i = 0; i
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 晚上泡红茶会失眠吗,喝乌龙茶是否会失眠
- 什么是802.11ax?它和WiFi 6 有什么关系呢?
- 灰度发布、蓝绿部署、金丝雀都是啥?
- web前端移动端最流行的网页布局技术:flexbox弹性布局学习详解
- 普洱茶源于什么,什么是普洱茶熟茶和普洱茶生茶
- 什么是Windows日志?
- 电脑安装什么杀毒软件?希望这篇文章能帮到你
- 串口服务器有什么作用?什么是文件服务器
- 编程为什么那么难:从储值卡扣款说起
- 什么红茶适合功夫茶具,怎么泡欧式红茶