2、netty粘包和半包实例代码,此代码会出现粘包示例,解决方法在下一篇

注:源代码来自享学课堂,学习之后所做笔记,方便回顾,也给大家一个参考

1、Client主函数

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.net.InetSocketAddress;

public class EchoClient {

    private final int port;
    private final String host;

    public EchoClient(int port, String host) {
        this.port = port;
        this.host = host;
    }
    //netty的标准程序基本都是下面这个流程
    public void start() throws InterruptedException {
        /*线程组*/
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            /*客户端启动必备,服务端使用ServerBootstrap*/
            Bootstrap b = new Bootstrap();
            b.group(group)
                    /*指明使用NIO进行网络通讯*/
                .channel(NioSocketChannel.class)
                    /*配置远程服务器的地址,服务器端就是配置LocalAdderss*/
                .remoteAddress(new InetSocketAddress(host,port))
                    //这里配置我们自定义的handler,netty主要就是写各种各样的handler
                .handler(new EchoClientHandler());
            /*连接到远程节点,阻塞等待直到连接完成*/
            ChannelFuture f = b.connect().sync();
            /*阻塞,直到channel关闭*/
            f.channel().closeFuture().sync();
        } finally {
            //阻塞关闭线程组
            group.shutdownGracefully().sync();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new EchoClient(8080,"127.0.0.1").start();
    }
}

2、自定义客户端Handler

在channelActive建立连接之后,循环100次数据,本来应该是server接受100次的,但是看最后的结果只接受了两次

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;

//SimpleChannelInboundHandler帮我们封装好了很多东西,客户端和服务端都是使用ByteBuf通信的
public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {

    /*客户端读取到服务器发送过来的数据了,在这里做处理*/
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg)
            throws Exception {
        System.out.println("Client accept:" + msg.toString(CharsetUtil.UTF_8));
    }

    /*客户端被通知channel活跃以后,做事*/
    //这里循环发送数据
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        for (int i = 0; i < 100; i++) {
            ctx.writeAndFlush(Unpooled.copiedBuffer("Hello,Netty ",
                    CharsetUtil.UTF_8));
        }
    }

    //客户端读取数据完毕之后做事
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelReadComplete");
    }

    //发生异常的处理
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

}

4、Server端主函数

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

import java.net.InetSocketAddress;

public class EchoServer  {

    private final int port;

    public EchoServer(int port) {
        this.port = port;
    }

    public static void main(String[] args) throws InterruptedException {
        int port = 8080;
        EchoServer echoServer = new EchoServer(port);
        System.out.println("服务器即将启动");
        echoServer.start();
        System.out.println("服务器关闭");
    }

    //代码大致和客户端相同,不同1\ServerBootstrap,2\childHandler
    public void start() throws InterruptedException {
        /*线程组*/
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();/*服务端启动必备*/
            b.group(group)
                    /*指明使用NIO进行网络通讯*/
            .channel(NioServerSocketChannel.class)
                    //.channel(EpollServerSocketChannel.class)
                    /*指明服务器监听端口*/
                    .localAddress(new InetSocketAddress(port))
                    /*接收到连接请求,新启一个socket通信,也就是channel,每个channel
                    * 有自己的事件的handler*/
                    .childOption(ChannelOption.TCP_NODELAY,true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new EchoServerHandler());
                        }
                    });
            ChannelFuture f = b.bind().sync();/*绑定到端口,阻塞等待直到连接完成*/
            /*阻塞,直到channel关闭*/
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully().sync();
        }
    }
}

5、server端的Handler

counter.incrementAndGet()用来计算客户端发送数据的次数,客户端循环了100次,但是服务端只接受了
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;

import java.util.concurrent.atomic.AtomicInteger;

/*指明我这个handler可以在多个channel之间共享,意味这个实现必须线程安全的。*/
@ChannelHandler.Sharable//如果不加这个注解,主函数在.childHandler(new EchoServerHandler()),确保每个链接都单独的handler
public class EchoServerHandler extends ChannelInboundHandlerAdapter {

    private AtomicInteger counter = new AtomicInteger();

    /*** 服务端读取到网络数据后的处理*/
    //计算接受数据次数,按道理客户端发送了100次,也应该接受100次,结果只有两次
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
            throws Exception {
        ByteBuf in = (ByteBuf) msg;/*netty实现的缓冲区*/
        System.out.println("Server Accept:" + in.toString(CharsetUtil.UTF_8) + counter.incrementAndGet());
        ctx.write(in);
    }

    /*** 服务端读取完成网络数据后的处理*/
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx)
            throws Exception {
        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)/*flush掉所有的数据*/
                .addListener(ChannelFutureListener.CLOSE);/*当flush完成后,关闭连接*/
    }

    /*** 发生异常后的处理*/
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

6、运行结果

server

服务器即将启动
Server Accept:Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hell1
Server Accept:o,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty Hello,Netty 2

这里只发生了两次,即粘包

client

Client accetp:Hello,Netty
channelReadComplete
channelReadComplete

Process finished with exit code 0

下一篇介绍netty解决粘包半包的三种基本方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值