io-4-netty-入门程序

netty入门小程序

server
public class TestNettyServer {

    public static void main(String[] args) {
        int port = 8888 ;
        try {
            new TestNettyServer().bind(port);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    private  void bind( int port) throws InterruptedException {
        //reactor线程组
        //用于服务端接受客户端连接
        EventLoopGroup boosGroup=new NioEventLoopGroup();
        //进行socketChannel 读写
        EventLoopGroup workGroup=new NioEventLoopGroup();
        try {
            // netty 服务端启动类
            ServerBootstrap serverBootstrap=new ServerBootstrap();
            serverBootstrap.group(boosGroup, workGroup)
                    //创建服务端
                    .channel(NioServerSocketChannel.class)
                    //设置tcp参数
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    //处理io事件
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() {

                                @Override
                                public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                    //super.channelRead(ctx, msg);
                                    ByteBuf buf = (ByteBuf)msg;
                                    // 创建域buf中可读字节数相同大小的数组
                                    byte[] req=new byte[buf.readableBytes()];
                                    //将缓冲区可读字节复制到req数组中
                                    buf.readBytes(req);
                                    System.out.println(" the time server receiver request :" + new String(req, "utf-8"));
                                    ByteBuf resp=Unpooled.copiedBuffer(new Date(System.currentTimeMillis()).toLocaleString().getBytes());
                                    //写回客户端
                                    ctx.write(resp);
                                }

                                @Override
                                public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
                                    //super.channelReadComplete(ctx);
                                    //刷新到缓冲数组中
                                    ctx.flush();
                                }

                                @Override
                                public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
                                    super.exceptionCaught(ctx, cause);
                                    ctx.close();
                                }
                            });
                        }
                    });
            //绑定端口,同步等待
            ChannelFuture future = serverBootstrap.bind(port).sync();
            future.channel().closeFuture().sync();
        }finally {
            //释放线程池资源
            boosGroup.shutdownGracefully();
            workGroup.shutdownGracefully();

        }

    }
}
//输出
//the time server receiver request : tell me the time 
client
public class TestNettyClient {

    public static void main(String[] args) throws InterruptedException {
        //客户端工作线程组
        EventLoopGroup clienGroup=new NioEventLoopGroup();
        //客户端netty服务启动
        Bootstrap bootstrap=new Bootstrap();
        try {
            bootstrap.group(clienGroup)
                    //客户端通道
                    .channel(NioSocketChannel.class)
                    //设置可选参数
                    .option(ChannelOption.TCP_NODELAY, true)
                    //处理io事件
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() {

                                @Override
                                public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                    //super.channelRead(ctx, msg);
                                    ByteBuf buf=(ByteBuf) msg;
                                    // 创建域buf中可读字节数相同大小的数组
                                    byte[] req=new byte[buf.readableBytes()];
                                    //将缓冲区可读字节复制到req数组中
                                    buf.readBytes(req);
                                    System.out.println(" client receive resp from server that the time is  :" + new String(req, "utf-8"));
                                }

                                @Override
                                public void channelActive(ChannelHandlerContext ctx) throws Exception {
                                    super.channelActive(ctx);
                                    //发送请求
                                    byte[] bytes=" tell me the time ".getBytes();
                                    ByteBuf buf=Unpooled.buffer(bytes.length);
                                    buf.writeBytes(bytes);
                                    ctx.writeAndFlush(buf);
                                }

                                @Override
                                public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
                                    super.exceptionCaught(ctx, cause);
                                    ctx.close();  //异常关闭资源
                                }
                            });
                        }
                    });
            ChannelFuture future=bootstrap.connect("127.0.0.1", 8888).sync();
            future.channel().closeFuture().sync();
        }finally {
            clienGroup.shutdownGracefully();
        }
    }
}
//输出
//client receive resp from server that the time is  :2017-7-21 0:23:54

Tcp粘包/拆包

    tcp在传输数据时,可能会拆分为多个包进行发送,也可能会将多个小包合并为一个大包发送。
    解决:
    1.消息定长发送;
    2.在包尾增加回车换车符进行分割
    3.将消息分为消息头和消息体,消息头中包含表示消息总长度的字段。
server
public class TestTcpServer {

    public static void main(String[] args) {
        int port=8888;
        try {
            new TestTcpServer().bind(port);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    private void bind(int port) throws InterruptedException {
        //reactor线程组
        //用于服务端接受客户端连接
        EventLoopGroup boosGroup=new NioEventLoopGroup();
        //进行socketChannel 读写
        EventLoopGroup workGroup=new NioEventLoopGroup();
        //记录客户端请求次数
        AtomicInteger atomicInteger=new AtomicInteger(0);
        try {
            // netty 服务端启动类
            ServerBootstrap serverBootstrap=new ServerBootstrap();
            serverBootstrap.group(boosGroup, workGroup)
                    //创建服务端
                    .channel(NioServerSocketChannel.class)
                    //设置tcp参数
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    //处理io事件
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //换行解码器
                            socketChannel.pipeline(). addLast(new LineBasedFrameDecoder(1024));
                            //直接将接受对象转化为String类型
                            socketChannel.pipeline().addLast(new StringDecoder());
                            //增加处理器
                            socketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() {

                                @Override
                                public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                    super.channelRead(ctx, msg);
                                    //ByteBuf buf=(ByteBuf) msg;
                                     创建域buf中可读字节数相同大小的数组
                                    //byte[] req=new byte[buf.readableBytes()];
                                    将缓冲区可读字节复制到req数组中
                                    //buf.readBytes(req);
                                    String req = (String)msg ;
                                    System.out.println(" the time server receiver request :"
                                            + req
                                            +" ; the count = " +  atomicInteger.incrementAndGet() );
                                    String response=new Date(System.currentTimeMillis()).toLocaleString() + System.getProperty("line.separator");
                                    ByteBuf resp=Unpooled.copiedBuffer(response.getBytes());
                                    //写回客户端
                                    ctx.write(resp);
                                }

                                @Override
                                public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
                                    //super.channelReadComplete(ctx);
                                    //刷新到缓冲数组中
                                    ctx.flush();
                                }

                                @Override
                                public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
                                    super.exceptionCaught(ctx, cause);
                                    ctx.close();
                                }
                            });
                        }
                    });
            //绑定端口,同步等待
            ChannelFuture future=serverBootstrap.bind(port).sync();
            future.channel().closeFuture().sync();
        } finally {
            //释放线程池资源
            boosGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
}
//输出
...
 the time server receiver request : tell me the time  ; the count = 99
 the time server receiver request : tell me the time  ; the count = 100
client
public class TestTcpServer {

    public static void main(String[] args) {
        int port=8888;
        try {
            new TestTcpServer().bind(port);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    private void bind(int port) throws InterruptedException {
        //reactor线程组
        //用于服务端接受客户端连接
        EventLoopGroup boosGroup=new NioEventLoopGroup();
        //进行socketChannel 读写
        EventLoopGroup workGroup=new NioEventLoopGroup();
        //记录客户端请求次数
        AtomicInteger atomicInteger=new AtomicInteger(0);
        try {
            // netty 服务端启动类
            ServerBootstrap serverBootstrap=new ServerBootstrap();
            serverBootstrap.group(boosGroup, workGroup)
                    //创建服务端
                    .channel(NioServerSocketChannel.class)
                    //设置tcp参数
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    //处理io事件
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //换行解码器
                            socketChannel.pipeline(). addLast(new LineBasedFrameDecoder(1024));
                            //直接将接受对象转化为String类型
                            socketChannel.pipeline().addLast(new StringDecoder());
                            //增加处理器
                            socketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() {

                                @Override
                                public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                    ////super.channelRead(ctx, msg);
                                    //ByteBuf buf=(ByteBuf) msg;
                                    //// 创建域buf中可读字节数相同大小的数组
                                    //byte[] req=new byte[buf.readableBytes()];
                                    ////将缓冲区可读字节复制到req数组中
                                    //buf.readBytes(req);
                                    String req = (String)msg ;
                                    System.out.println(" the time server receiver request :"
                                            + req
                                            +" ; the count = " +  atomicInteger.incrementAndGet() );
                                    String response=new Date(System.currentTimeMillis()).toLocaleString() + System.getProperty("line.separator");
                                    ByteBuf resp=Unpooled.copiedBuffer(response.getBytes());
                                    //写回客户端
                                    ctx.write(resp);
                                }

                                @Override
                                public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
                                    //super.channelReadComplete(ctx);
                                    //刷新到缓冲数组中
                                    ctx.flush();
                                }

                                @Override
                                public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
                                    super.exceptionCaught(ctx, cause);
                                    ctx.close();
                                }
                            });
                        }
                    });
            //绑定端口,同步等待
            ChannelFuture future=serverBootstrap.bind(port).sync();
            future.channel().closeFuture().sync();
        } finally {
            //释放线程池资源
            boosGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
}
//输出
client receive resp from server that the time is  :2017-7-21 15:47:33 ; count  = 98
 client receive resp from server that the time is  :2017-7-21 15:47:33 ; count  = 99     
 client receive resp from server that the time is  :2017-7-21 15:47:33 ; count  = 100
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值