netty的Helloworld---netty学习笔记

参考学习文章:http://ifeve.com/netty5-user-guide/

Server类:
package com.zyh.study.netty.helloworld;

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

/**
 * @Description:
 * @Author: zyh
 * @Date: created in 2018/7/22
 */
public class Server {
    public static void main(String[] args) throws Exception {
        //用于处理服务器端接受客户端连接的线程组
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        //用于进行网络通讯(读写)的线程组
        NioEventLoopGroup workGroup = new NioEventLoopGroup();

        //创建辅助工具类,用于服务器通道的一系列的配置
        ServerBootstrap sb = new ServerBootstrap();
        sb.group(bossGroup,workGroup)//绑定两个线程组
                .channel(NioServerSocketChannel.class)//指定NIO的网络传输模式为TCP,UDP:NioDatagramChannel
                .option(ChannelOption.SO_BACKLOG,1024)//设置tcp缓冲
                .option(ChannelOption.SO_SNDBUF,32*1024)//设置发送缓冲大小
                .option(ChannelOption.SO_RCVBUF,32*1024)//设置接收缓冲大小
                .option(ChannelOption.SO_KEEPALIVE,true)//保持连接
                .childHandler(new ChannelInitializer() {
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast(new ServerHandler());//这里配置具体数据接收方法的处理
                    }
                });

        ChannelFuture cf1 = sb.bind(8787).sync();//异步的绑定指定的端口
        ChannelFuture cf2 = sb.bind(8686).sync();//netty可以绑定多个端口

        cf1.channel().closeFuture().sync();//等待关闭,相当于Thread.sleep(Integer.MAX_VALUE)
        cf2.channel().closeFuture().sync();

        //关闭线程组
        bossGroup.shutdownGracefully();
        workGroup.shutdownGracefully();
    }
}
ServerHandler类:(用于处理server接收到的消息)
package com.zyh.study.netty.helloworld;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

/**
 * @Description:
 * @Author: zyh
 * @Date: created in 2018/7/22
 */
public class ServerHandler extends ChannelHandlerAdapter{

    /**
     * 重写读数据时处理的方法
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        ByteBuf buf = (ByteBuf) msg;

        //声明字节数组,buf.readableBytes()返回的是buf缓冲中可读的字节数
        byte[] req = new byte[buf.readableBytes()];
        //将buf缓冲区中的字节读取到字节数组req中
        buf.readBytes(req);
        String body = new String(req, "utf-8");
        System.out.println("Server打印接收到的信息:" + body);
        String response = "Server返回给Client的响应信息:" + body;

        //1.ctx.writeAndFlush()方法相当于连续调用了write()和flush()方法,因为write()方法只是将buf写到了渠道的缓冲区中,flush()方法会将缓冲区中的数据传给客户端
        //2.这里Unpooled工具类的作用就是讲字节数组转成netty的ByteBuf对象
        //3.这里使用了writeAndFlush()方法会自动释放buf缓冲区所以不需要想ClientHandler中那样finally中手动释放buf缓冲区了
        //4.addListener()方法:当监听到服务器将数据写给客户端,并且确认客户端已经收到信息后,
        // 服务器端就会主动去关闭跟客户端的连接,因为客户端调用了cf1.channel().closeFuture().sync()方法,所以客户端这里的阻塞就会打开,继续向后执行代码
        ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()));
//                .addListener(ChannelFutureListener.CLOSE);
    }

    /**
     * 重写读数据出现异常处理的方法
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}

Client类:
package com.zyh.study.netty.helloworld;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

/**
 * @Description:
 * @Author: zyh
 * @Date: created in 2018/7/22
 */
public class Client {
    public static void main(String[] args) throws Exception{

        NioEventLoopGroup group = new NioEventLoopGroup();//用于处理网络通信(读写)的线程组

        Bootstrap b = new Bootstrap();//创建客户端辅助类工具
        b.group(group)//绑定线程组
                .channel(NioSocketChannel.class)//设置通信渠道为TCP协议
                .handler(new ChannelInitializer() {
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast(new ClientHandler());//这里配置具体数据接收方法的处理
                    }
                });

        /*与8787端口通讯*/
        ChannelFuture cf1 = b.connect("127.0.0.1", 8787).sync();//异步建立连接

        cf1.channel().write(Unpooled.copiedBuffer("hello world".getBytes()));//将“hello world”写到buf缓冲区
        cf1.channel().flush();//这里必须使用flush(),只用冲刷才能将buf缓冲区中的数据传给服务器端

        /*与8686端口通讯*/
        ChannelFuture cf2 = b.connect("127.0.0.1", 8686).sync();
        cf2.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty".getBytes()));

        cf1.channel().closeFuture().sync();//等待关闭,相当于Thread.sleep(Integer.MAX_VALUE)
        cf2.channel().closeFuture().sync();

        group.shutdownGracefully();//关闭线程组
    }
}

ClientHandler类:(用于处理Client端接收到的消息)
package com.zyh.study.netty.helloworld;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;

import java.nio.ByteBuffer;

/**
 * @Description:
 * @Author: zyh
 * @Date: created in 2018/7/22
 */
public class ClientHandler extends ChannelHandlerAdapter {

    /**
     * 重写读数据时处理的方法
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            ByteBuf buf = (ByteBuf) msg;

            //声明字节数组,buf.readableBytes()返回的是buf缓冲中可读的字节数
            byte[] req = new byte[buf.readableBytes()];
            buf.readBytes(req);
            String body = new String(req, "utf-8");
            System.out.println("Client打印接收到的信息:" + body);

        }finally {
            ReferenceCountUtil.release(msg);//buf缓冲区使用完了,必须释放
        }

    }

    /**
     * 重写读数据出现异常处理的方法
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}

你可能感兴趣的:(netty的Helloworld---netty学习笔记)