• Netty4.0学习笔记系列之一:Server与Client的通讯


    本文是学习Netty的第一篇文章,主要对Netty的Server和Client间的通讯机制进行验证。

    Server与Client建立连接后,会执行以下的步骤:

    1、Client向Server发送消息:Are you ok?

    2、Server接收客户端发送的消息,并打印出来。

    3、Server端向客户端发送消息:I am ok!

    4、Client接收Server端发送的消息,并打印出来,通讯结束。

    涉及到的类有4个:

    1、HelloServer :server类,启动Netty server

    2、HelloServerInHandler:server的handler,接收客户端消息,并向客户端发送消息

    3、HelloClient:client类,建立于Netty server的连接

    4、HelloClientIntHandler:client的handler,接收server端的消息,并向服务端发送消息

    1、HelloServer代码如下:

    [java] view plain copy
    1. package com.guowl.testserver;  
    2.   
    3. import io.netty.bootstrap.ServerBootstrap;  
    4. import io.netty.channel.ChannelFuture;  
    5. import io.netty.channel.ChannelInitializer;  
    6. import io.netty.channel.ChannelOption;  
    7. import io.netty.channel.EventLoopGroup;  
    8. import io.netty.channel.nio.NioEventLoopGroup;  
    9. import io.netty.channel.socket.SocketChannel;  
    10. import io.netty.channel.socket.nio.NioServerSocketChannel;  
    11.   
    12. public class HelloServer {  
    13.     public void start(int port) throws Exception {  
    14.         EventLoopGroup bossGroup = new NioEventLoopGroup();  
    15.         EventLoopGroup workerGroup = new NioEventLoopGroup();  
    16.         try {  
    17.             ServerBootstrap b = new ServerBootstrap();  
    18.             b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)  
    19.                     .childHandler(new ChannelInitializer<SocketChannel>() {  
    20.                         @Override  
    21.                         public void initChannel(SocketChannel ch)  
    22.                                 throws Exception {  
    23.                             // 注册handler  
    24.                             ch.pipeline().addLast(new HelloServerInHandler());  
    25.                         }  
    26.                     }).option(ChannelOption.SO_BACKLOG, 128)  
    27.                     .childOption(ChannelOption.SO_KEEPALIVE, true);  
    28.   
    29.             ChannelFuture f = b.bind(port).sync();  
    30.   
    31.             f.channel().closeFuture().sync();  
    32.         } finally {  
    33.             workerGroup.shutdownGracefully();  
    34.             bossGroup.shutdownGracefully();  
    35.         }  
    36.     }  
    37.   
    38.     public static void main(String[] args) throws Exception {  
    39.         HelloServer server = new HelloServer();  
    40.         server.start(8000);  
    41.     }  
    42. }  


    2、HelloServerInHandler代码如下:

    [java] view plain copy
    1. package com.guowl.testserver;  
    2.   
    3. import io.netty.buffer.ByteBuf;  
    4. import io.netty.channel.ChannelHandlerContext;  
    5. import io.netty.channel.ChannelInboundHandlerAdapter;  
    6.   
    7. import org.slf4j.Logger;  
    8. import org.slf4j.LoggerFactory;  
    9.   
    10. // 该handler是InboundHandler类型  
    11. public class HelloServerInHandler extends ChannelInboundHandlerAdapter {  
    12.     private static Logger logger = LoggerFactory  
    13.             .getLogger(HelloServerInHandler.class);  
    14.   
    15.     @Override  
    16.     public void channelRead(ChannelHandlerContext ctx, Object msg)  
    17.             throws Exception {  
    18.         logger.info("HelloServerInHandler.channelRead");  
    19.         ByteBuf result = (ByteBuf) msg;  
    20.         byte[] result1 = new byte[result.readableBytes()];  
    21.         // msg中存储的是ByteBuf类型的数据,把数据读取到byte[]中  
    22.         result.readBytes(result1);  
    23.         String resultStr = new String(result1);  
    24.         // 接收并打印客户端的信息  
    25.         System.out.println("Client said:" + resultStr);  
    26.         // 释放资源,这行很关键  
    27.         result.release();  
    28.   
    29.         // 向客户端发送消息  
    30.         String response = "I am ok!";  
    31.         // 在当前场景下,发送的数据必须转换成ByteBuf数组  
    32.         ByteBuf encoded = ctx.alloc().buffer(4 * response.length());  
    33.         encoded.writeBytes(response.getBytes());  
    34.         ctx.write(encoded);  
    35.         ctx.flush();  
    36.     }  
    37.   
    38.     @Override  
    39.     public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {  
    40.         ctx.flush();  
    41.     }  
    42. }  


    3、HelloClient代码如下:

    [java] view plain copy
    1. package com.guowl.testserver;  
    2.   
    3. import io.netty.bootstrap.Bootstrap;  
    4. import io.netty.channel.ChannelFuture;  
    5. import io.netty.channel.ChannelInitializer;  
    6. import io.netty.channel.ChannelOption;  
    7. import io.netty.channel.EventLoopGroup;  
    8. import io.netty.channel.nio.NioEventLoopGroup;  
    9. import io.netty.channel.socket.SocketChannel;  
    10. import io.netty.channel.socket.nio.NioSocketChannel;  
    11.   
    12. public class HelloClient {  
    13.     public void connect(String host, int port) throws Exception {  
    14.         EventLoopGroup workerGroup = new NioEventLoopGroup();  
    15.   
    16.         try {  
    17.             Bootstrap b = new Bootstrap();  
    18.             b.group(workerGroup);  
    19.             b.channel(NioSocketChannel.class);  
    20.             b.option(ChannelOption.SO_KEEPALIVE, true);  
    21.             b.handler(new ChannelInitializer<SocketChannel>() {  
    22.                 @Override  
    23.                 public void initChannel(SocketChannel ch) throws Exception {  
    24.                     ch.pipeline().addLast(new HelloClientIntHandler());  
    25.                 }  
    26.             });  
    27.   
    28.             // Start the client.  
    29.             ChannelFuture f = b.connect(host, port).sync();  
    30.   
    31.             // Wait until the connection is closed.  
    32.             f.channel().closeFuture().sync();  
    33.         } finally {  
    34.             workerGroup.shutdownGracefully();  
    35.         }  
    36.   
    37.     }  
    38.   
    39.     public static void main(String[] args) throws Exception {  
    40.         HelloClient client = new HelloClient();  
    41.         client.connect("127.0.0.1", 8000);  
    42.     }  
    43. }  

    4、HelloClientIntHandler代码如下:

    [java] view plain copy
    1. package com.guowl.testserver;  
    2.   
    3. import io.netty.buffer.ByteBuf;  
    4. import io.netty.channel.ChannelHandlerContext;  
    5. import io.netty.channel.ChannelInboundHandlerAdapter;  
    6.   
    7. import org.slf4j.Logger;  
    8. import org.slf4j.LoggerFactory;  
    9.   
    10. public class HelloClientIntHandler extends ChannelInboundHandlerAdapter {  
    11.     private static Logger logger = LoggerFactory.getLogger(HelloClientIntHandler.class);  
    12.   
    13.     // 接收server端的消息,并打印出来  
    14.     @Override  
    15.     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {  
    16.         logger.info("HelloClientIntHandler.channelRead");  
    17.         ByteBuf result = (ByteBuf) msg;  
    18.         byte[] result1 = new byte[result.readableBytes()];  
    19.         result.readBytes(result1);  
    20.         System.out.println("Server said:" + new String(result1));  
    21.         result.release();  
    22.     }  
    23.   
    24.     // 连接成功后,向server发送消息  
    25.     @Override  
    26.     public void channelActive(ChannelHandlerContext ctx) throws Exception {  
    27.         logger.info("HelloClientIntHandler.channelActive");  
    28.         String msg = "Are you ok?";  
    29.         ByteBuf encoded = ctx.alloc().buffer(4 * msg.length());  
    30.         encoded.writeBytes(msg.getBytes());  
    31.         ctx.write(encoded);  
    32.         ctx.flush();  
    33.     }  
    34. }  


    通过上面简单的实例可以发现:

    1、在没有任何encoder、decoder的情况下,Netty发送接收数据都是按照ByteBuf的形式,其它形式都是不合法的。

    2、接收发送数据操作都是通过handler实现的,handler在netty中占据了非常重要的位置。

    3、netty的handler是基于事件触发的,例如当client连接server成功后,client中的HelloClientIntHandler的channelActive方法会自动调用。

  • 相关阅读:
    什么是PV UV PR值
    手工测试了各个搜索引擎对博客文章的收录
    Linux 常用命令
    部分linux命令详解
    左右滑屏的实现
    网络资源下载时断点续传的实现
    MYSQL5.5.37win32.msi 这个版本得程序包谁有吗 可以给我一下吗?
    Linux(CentOS6.5) 开放端口,配置防火墙
    centos7 下出现 yum list 报错 还有yum groupolist 查询软件组列表报错
    linux命令(1):ls命令
  • 原文地址:https://www.cnblogs.com/zeroone/p/8490944.html
Copyright © 2020-2023  润新知