录:

1、TCP 粘包和拆包基本介绍
2、TCP 粘包和拆包 实例演示
3、netty 自定义协议解决 TCP 粘包和拆包

 

1、TCP 粘包和拆包基本介绍    <--返回目录

  TCP 是面向连接的,面向流的,提供高可靠性服务,收发两端(客户端和服务器端)都要一 一成对的 socket。因此发送端为了将多个发给接收端的包更有效的发给对方,使用了优化方法(Nagle 算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样虽然提高了效率,但是接收端就难于分辨出完整的数据包了,因为面向流的通信是无消息保护边界的。

  由TCP 无消息保护边界,需要在接收端处理消息边界问题,也就是我们所说的粘包、拆包问题。

netty 详解(七)netty 自定义协议解决 TCP 粘包和拆包

 

2、TCP 粘包和拆包 实例演示    <--返回目录

  在编写 netty 程序时,如果没有做处理,就会发生粘包和拆包的问题。看一个具体的实例:

netty 详解(七)netty 自定义协议解决 TCP 粘包和拆包

   Server 端程序

package com.oy.tcp;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class Server {
    public static void main(String[] args) {
        NioEventLoopGroup boss = new NioEventLoopGroup(1);
        NioEventLoopGroup work = new NioEventLoopGroup();

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap
                    .group(boss, work)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new MyServerHandler());
                        }
                    });
            ChannelFuture future = serverBootstrap.bind(8005).sync();
            System.out.println("server started and listen " + 8005);
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            boss.shutdownGracefully();
            work.shutdownGracefully();
        }
    }
}


package com.oy.tcp;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.CharsetUtil;

import java.util.UUID;

public class MyServerHandler extends SimpleChannelInboundHandler<ByteBuf> {
    private int count;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
        //System.out.println("服务器收到的数据:" + msg.toString(CharsetUtil.UTF_8));
        byte[] buffer = new byte[msg.readableBytes()];
        msg.readBytes(buffer);

        // 将 buffer 转成字符串
        String  message = new String(buffer, CharsetUtil.UTF_8);
        System.out.println("服务器接收数据 " + message);
        System.out.println("服务器接收到消息量= " + (++this.count));

        // 服务器会送数据
        ByteBuf response = Unpooled.copiedBuffer(UUID.randomUUID().toString(), CharsetUtil.UTF_8);
        ctx.writeAndFlush(response);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}
View Code

相关文章:

  • 2021-05-31
  • 2021-10-02
  • 2022-12-23
  • 2021-05-26
  • 2021-11-01
  • 2021-11-04
  • 2021-10-20
  • 2021-10-05
猜你喜欢
  • 2021-08-26
  • 2021-05-29
  • 2022-12-23
  • 2022-01-15
  • 2022-12-23
相关资源
相似解决方案