前面文章讲了如何通过Netty3写一个简单的例子,但是Netty4和Netty5同Netty3有很大的不同,这篇文章简单介绍下如何通过Netty5写一个简单的服务端和客户端例子。

服务端

1. 初始化一个NIO辅助服务类

//NIO服务的辅助启动类
        ServerBootstrap bootstrap = new ServerBootstrap();

2. 初始化两个处理IO操作的多线程事件循环器,一个用于接收连接,一个用于处理客户端i/o事件

//boss和worker
        //EventLoopGroup是用来处理IO操作的多线程事件循环器

        //负责接收客户端连接线程
        EventLoopGroup boss = new NioEventLoopGroup();
        //负责处理客户端i/o事件、task任务、监听任务组
        EventLoopGroup worker = new NioEventLoopGroup();

3. 设置服务端服务类的一些参数,包括channel绑定,事件循环器绑定等

//设置线程池
            bootstrap.group(boss, worker);
            //配置 Channel
            bootstrap.channel(NioServerSocketChannel.class);

            bootstrap.childHandler(new ChannelInitializer<Channel>() {

                protected void initChannel(Channel ch) throws Exception {
                    ch.pipeline().addLast(new StringDecoder());
                    ch.pipeline().addLast(new StringEncoder());
                    ch.pipeline().addLast(new ServerHanler());
                }

            });
            //BACKLOG用于构造服务端套接字ServerSocket对象,
            // 标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度
            bootstrap.option(ChannelOption.SO_BACKLOG, 2048);
            //是否启用心跳保活机制
            bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
            bootstrap.childOption(ChannelOption.TCP_NODELAY, true);

这里注册了一个自定义的事件处理的类ServerHanler,该类继承于SimpleChannelInboundHandler<String>,ServerHanler主要处理代码如下:

@Override
    protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {
        System.out.println(msg);
        ctx.channel().writeAndFlush("hi");
        ctx.writeAndFlush("hi");

    }

4. 绑定端口,开始监听连接,并阻塞主线程退出

ChannelFuture future = bootstrap.bind(10010);
            System.out.println("start");
            //服务器关闭监听
            /*channel.closeFuture().sync()实际是如何工作:
            channel.closeFuture()不做任何操作,只是简单的返回channel对象中的closeFuture对象,对于每个Channel对象,都会有唯一的一个CloseFuture,用来表示关闭的Future,
            所有执行channel.closeFuture().sync()就是执行的CloseFuturn的sync方法,从上面的解释可以知道,这步是会将当前线程阻塞在CloseFuture上*/
            future.channel().closeFuture().sync();

客户端

1. 初始化一个NIO辅助服务类

//服务类
        Bootstrap bootstrap=new Bootstrap();

2. 初始化一个处理IO操作的多线程循环处理器

//worker
        EventLoopGroup worker=new NioEventLoopGroup();

3. 设置NIO辅助类的一些属性,包括指定多线程循环处理器、指定channel和指定初始化处理操作

//设置IO多线程循环处理器
            bootstrap.group(worker);

            //设置Channel
            bootstrap.channel(NioSocketChannel.class);

            //指定客户端初始化处理操作
            bootstrap.handler(new ChannelInitializer<Channel>() {

                @Override
                protected void initChannel(Channel ch) throws  Exception{
                    ch.pipeline().addLast(new StringDecoder());
                    ch.pipeline().addLast(new StringEncoder());
                    ch.pipeline().addLast(new ClientHandler());
                }
            });

 此处有一个处理消息的自定义类ClientHandler,继承自SimpleChannelInboundHandler<String>,ClientHandler主要代码如下:

@Override
    protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {
        System.out.println("客户端收到消息:"+msg);
    }

4. 开始连接服务端

ChannelFuture connect=bootstrap.connect("127.0.0.1",10010);

5.开始进行发送消息

BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(System.in));
            while (true){
                System.out.println("请输入:");
                String msg= bufferedReader.readLine();
                connect.channel().writeAndFlush(msg);
            }