Netty基础操作实例

netty的简介

Netty是基于Java NIO的网络应用框架.
Netty是一个NIOclient-server(客户端服务器)框架,使用Netty可以快速开发网络应用,
例如服务器和客户端协议。Netty提供了一种新的方式来使开发网络应用程序,这种新的
方式使得它很容易使用和有很强的扩展性。Netty的内部实现时很复杂的,但是Netty提
供了简单易用的api从网络处理代码中解耦业务逻辑。Netty是完全基于NIO实现的,所以
整个Netty都是异步的。
网络应用程序通常需要有较高的可扩展性,无论是Netty还是其他的基于Java NIO的框
架,都会提供可扩展性的解决方案。Netty中一个关键组成部分是它的异步特性.

客户端

1,客户端启动类

public class NettyClientImpl {
    private final String ip;
    private final int port;

    public NettyClientImpl(String ip, int port) {
        this.ip = ip;
        this.port = port;
    }

    public static void main(String[] args) throws InterruptedException {
        new NettyClientImpl("127.0.0.1", 20207).netClientStart();
    }
        public void netClientStart() throws InterruptedException {
        //可以理解为一个线程池,用来处理连接,接收数据和发送数据
        EventLoopGroup elg = null;
        try {
            elg = new NioEventLoopGroup();
            Bootstrap bootstrap = new Bootstrap();//客户端引导类
            bootstrap.group(elg)
                    .channel(NioSocketChannel.class)//指定通道类型为NioSocketChannel,一种异步模式
                    .remoteAddress(ip,port)//设置客户端发送请求的ip和端口号
                    .handler(new ChannelInitializer<SocketChannel>() {//业务处理类
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            /**设置执行流程,可以有多个inboundhandler和outboundhandler;
                             * 执行时inboundhandler按添加顺序执行,outboundhandler按添加的反顺序执行
                             * 添加时,最后一个添加的不能是outboundhandler
                             */
                            socketChannel.pipeline().addLast(new ClientHandler());//注册handler
                        }
            });
            //连接服务器,sync():一直连接,直到连接成功
            ChannelFuture future = bootstrap.connect().sync();
//            future.channel().writeAndFlush(new Object()).sync();//可以用来发送数据
            //直到获取到返回结果后才关闭
            future.channel().closeFuture().sync();
        }  finally {
            //直到所有工作完成后,关闭连接
            elg.shutdownGracefully().sync();
        }
    }
}

2,客户端执行流程类

public class ClientHandler extends SimpleChannelInboundHandler {
    //客户端连接服务器后被调用
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("向服务端发送数据..........");
        Person person = new Person("可达鸭","man",2);
        //数据传输必须是字节数组,需要进行编码、解码才可以获取到实际的数据
        byte[] bytes = ObjectToByteUtils.objectToBytes(person);//通过ObjectOutputStream将数据编码
        ByteBuf byteBuf = Unpooled.copiedBuffer(bytes);
        //发送数据
        ctx.write(byteBuf);
        ctx.flush();
    }
    //接收到服务端返回的数据后被调用
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
        //读取服务端返回数据
        ByteBuf byteBuf = (ByteBuf) o;
        byte[] bytes = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(bytes);
        Person person = (Person) ObjectToByteUtils.bytesToObject(bytes);//通过ObjectInputStream将数据解码
        System.out.println(person);
    }
    //出现异常被调用
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}

服务端

1,服务端启动类

public class NettyServerImpl {
    private final int port;

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

    public static void main(String[] args) throws InterruptedException {
        new NettyServerImpl(20207).netServerStart();
    }
    public void netServerStart() throws InterruptedException {
        //相当于一个线程池,用来处理连接,发送数据和处理数据
        EventLoopGroup elg = null;
        try{
            elg = new NioEventLoopGroup();
            //服务端引导类
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(elg)//多线程处理
                    .channel(NioServerSocketChannel.class)//指定服务端通道类型
                    .localAddress("localhost",port)//设置监听的ip和端口
                    .childHandler(new ChannelInitializer<Channel>() {//业务处理
                @Override
                protected void initChannel(Channel channel) throws Exception {
                    channel.pipeline().addLast(new ServerHandlerImpl());//设置执行流程
                }
            });
            //绑定服务器,直到完成绑定,调用sync()会阻塞,
            ChannelFuture future = serverBootstrap.bind().sync();
            System.out.println("开始监听,监听端口为...."+future.channel().localAddress());
            future.channel().closeFuture().sync();//直到拿到结果后才关闭
        }finally {
            elg.shutdownGracefully().sync();
        }
    }
}

2,服务端执行流程类

public class ServerHandlerImpl extends SimpleChannelInboundHandler {
    //接收到客户端发送的数据时调用
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
        //读取客户端传过来的数据
        ByteBuf byteBuf = (ByteBuf) o;
        byte[] bytes = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(bytes);
        Person person = (Person) ObjectToByteUtils.bytesToObject(bytes);//通过ObjectInputStream将数据解码
        System.out.println(person);

    }
    //服务端处理完成数据时调用
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        //服务端向客户端发送数据
        Person person = new Person("槑の少年","man",23);
        byte[] bytes = ObjectToByteUtils.objectToBytes(person);
        ByteBuf byteBuf = Unpooled.copiedBuffer(bytes);
        //发送数据
        ctx.write(byteBuf);
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值