1. server
1 public class Server { 2 3 public static void main(String[] args) throws Exception { 4 System.out.println("Server is starting..."); 5 //1 创建线两个程组 6 EventLoopGroup bossGroup = new NioEventLoopGroup(); //一个是用于处理服务器端接收客户端连接的 7 EventLoopGroup workGroup = new NioEventLoopGroup(); //一个是进行网络通信的(网络读写的) 8 9 //2 创建辅助工具类,用于服务器通道的一系列配置 10 ServerBootstrap b = new ServerBootstrap(); 11 b.group(bossGroup, workGroup) //绑定俩个线程组 12 .channel(NioServerSocketChannel.class) //指定NIO的模式 13 .option(ChannelOption.SO_BACKLOG, 1024) //设置tcp缓冲区 14 .option(ChannelOption.SO_SNDBUF, 32*1024) //设置发送缓冲大小 15 .option(ChannelOption.SO_RCVBUF, 32*1024) //这是接收缓冲大小 16 .option(ChannelOption.SO_KEEPALIVE, true) //保持连接 17 .childHandler(new ChannelInitializer<SocketChannel>() {//服务端就是childHandler 18 @Override 19 protected void initChannel(SocketChannel socketChannel) throws Exception { 20 //3 在这里配置具体数据接收方法的处理 ChannelPipeline<<<添加到<<-ChannelHandler 21 socketChannel.pipeline().addLast(new ServerHandler()); 22 } 23 }); 24 25 //4 异步,进行绑定 服务端是bind,客户端是connect 26 ChannelFuture channelFuture = b.bind(8765).sync(); 27 //5 等待关闭 28 channelFuture.channel().closeFuture().sync(); // 阻塞用, 等价于Thread.sleep(Integer.MAX_VALUE) 29 30 bossGroup.shutdownGracefully(); 31 workGroup.shutdownGracefully(); 32 } 33 }
1.2 ServerHandler
1 //服务端业务逻辑处理类 2 public class ServerHandler extends ChannelHandlerAdapter { 3 @Override 4 public void channelActive(ChannelHandlerContext ctx) throws Exception { 5 System.out.println("server channel active... "); 6 } 7 8 @Override //Object msg 服务端接收到的客户端请求的数据封装到object对象中 9 public void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception { 10 ByteBuf buf = (ByteBuf) msg; 11 byte[] req = new byte[buf.readableBytes()]; 12 buf.readBytes(req);//先读到字节数组中 13 String body = new String(req, "utf-8"); 14 System.out.println("Server接收到客户端请求:"+body); 15 String response = "Hi Client, I am Server! you send " + body+"to me???" ; 16 //Unpooled.copiedBuffer(response.getBytes()将string-->byte[]--->ByteBuf 17 ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes())); 18 //.addListener(ChannelFutureListener.CLOSE); 19 } 20 21 @Override 22 public void channelReadComplete(ChannelHandlerContext ctx)throws Exception { 23 System.out.println("读完了"); 24 ctx.flush(); 25 } 26 27 @Override 28 public void exceptionCaught(ChannelHandlerContext ctx, Throwable t)throws Exception { 29 ctx.close(); 30 } 31 32 }
2. client
1 public class Client { 2 public static void main(String[] args) throws Exception{ 3 System.out.println("Client is Starting..."); 4 EventLoopGroup group = new NioEventLoopGroup();//客户端一个线程组,发送请求即可 5 Bootstrap b = new Bootstrap(); //辅助类, 服务端为ServerBootstrap 6 b.group(group) 7 .channel(NioSocketChannel.class) 8 .handler(new ChannelInitializer<SocketChannel>() {//服务端为childHandler(...) 9 @Override 10 protected void initChannel(SocketChannel socketChannel) throws Exception { 11 socketChannel.pipeline().addLast(new ClientHandler());//ChannelPipeline.addLast 12 } 13 }); 14 15 ChannelFuture channelFuture = b.connect("127.0.0.1", 8765).sync(); 16 //发送消息 17 Thread.sleep(1000); 18 channelFuture.channel().writeAndFlush(Unpooled.copiedBuffer("Client: Hi Server, I am client netty!".getBytes())); 19 channelFuture.channel().writeAndFlush(Unpooled.copiedBuffer("client request 666".getBytes())); 20 Thread.sleep(2000); 21 channelFuture.channel().writeAndFlush(Unpooled.copiedBuffer("client request 888".getBytes())); 22 23 channelFuture.channel().closeFuture().sync();//阻塞 24 group.shutdownGracefully(); 25 } 26 }
3. ClientHandler
1 //客户端业务处理类 2 public class ClientHandler extends ChannelHandlerAdapter{ 3 @Override 4 public void channelActive(ChannelHandlerContext ctx) throws Exception { 5 } 6 7 @Override //Object msg 客户端接收到的服务端响应的数据封装为object对象 8 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 9 try { 10 ByteBuf buf = (ByteBuf) msg; 11 byte[] req = new byte[buf.readableBytes()]; //创建一个字节数组 12 buf.readBytes(req); //把数据先读到字节数组中 13 String body = new String(req, "utf-8"); 14 String response = "Client: 收到服务器端的返回信息:" + body; 15 System.out.println(response); 16 } finally { 17 ReferenceCountUtil.release(msg); //服务端在writeAndFlush的时候自动释放了, 客户端没调用write方法需要手动释放 18 } 19 } 20 21 @Override 22 public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 23 24 } 25 26 @Override 27 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) 28 throws Exception { 29 ctx.close(); 30 } 31 32 }
1 结果: 2 Client is Starting... 3 Client: 收到服务器端的返回信息:Hi Client, I am Server! you send Client: Hi Server, I am client netty!client request 666to me??? 4 Client: 收到服务器端的返回信息:Hi Client, I am Server! you send client request 888to me??? 5 6 ------------------------------------------------------- 7 8 Server is starting... 9 server channel active... 10 Server接收到客户端请求:Client: Hi Server, I am client netty!client request 666 11 读完了 12 Server接收到客户端请求:client request 888 13 读完了
4. 如果想单次连接后得到响应,就关闭客户端,必须在server端关闭. .addListener(ChannelFutureListener.CLOSE)
1 //服务端业务逻辑处理类 2 public class ServerHandler extends ChannelHandlerAdapter { 3 @Override 4 public void channelActive(ChannelHandlerContext ctx) throws Exception { 5 System.out.println("server channel active... "); 6 } 7 8 @Override //Object msg 服务端接收到的客户端请求的数据封装到object对象中 9 public void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception { 10 ByteBuf buf = (ByteBuf) msg; 11 byte[] req = new byte[buf.readableBytes()]; 12 buf.readBytes(req);//先读到字节数组中 13 String body = new String(req, "utf-8"); 14 System.out.println("Server接收到客户端请求:"+body); 15 String response = "Hi Client, I am Server! you send " + body+"to me???" ; 16 //Unpooled.copiedBuffer(response.getBytes()将string-->byte[]--->ByteBuf 17 ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes())) 18 .addListener(ChannelFutureListener.CLOSE);//关闭通道必须在Server端,一次连接后就关闭 19 } 20 21 @Override 22 public void channelReadComplete(ChannelHandlerContext ctx)throws Exception { 23 System.out.println("读完了"); 24 ctx.flush(); 25 } 26 27 @Override 28 public void exceptionCaught(ChannelHandlerContext ctx, Throwable t)throws Exception { 29 ctx.close(); 30 } 31 32 }
效果: 客户端只能收到服务器端一条响应
1 Client is Starting... 2 Client: 收到服务器端的返回信息:Hi Client, I am Server! you send Client: Hi Server, I am client netty!client request 666to me???