文档章节

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

何昀
 何昀
发布于 2016/06/13 16:25
字数 806
阅读 101
收藏 0

本文是学习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

 在CODE上查看代码片派生到我的代码片

  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

 在CODE上查看代码片派生到我的代码片

  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

 在CODE上查看代码片派生到我的代码片

  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

 在CODE上查看代码片派生到我的代码片

  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方法会自动调用。

本文转载自:http://blog.csdn.net/u013252773/article/details/21608951

何昀
粉丝 0
博文 6
码字总数 0
作品 0
南宁
私信 提问
NodeJS系列~第三个小例子,NodeJs与Redis实现高并发的队列存储

众所周知 redis量个强大的缓存组件,可以部署在win32和linux环境之上,它有五大存储结构,其中有一种为列表list,它可以实现quene和stack的功能,即队列和堆栈的功能。 redis相关文章,可以看...

mcy247
2017/12/06
0
0
12.5-全栈Java笔记:Java网络编程(三)

上节回顾:在学习了Socket在建立客户端和服务器单项通讯中,分别创建独立的Socket,并通过Socket的属性。 那么如何将两个Socket进行连接,从而达到客户端和服务器之间建立输入输出流进行通信...

全栈Java
2018/06/26
0
0
MyBatis学习笔记系列教程

【MyBatis学习笔记】系列之预备篇一:ant的下载与安装 【MyBatis学习笔记】系列之预备篇二:ant入门示例 【MyBatis学习笔记】系列之一:MyBatis入门示例 【MyBatis学习笔记】系列之二:MyBat...

HenrySun
2016/10/15
153
0
ZooKeeper教程资源收集(简介/原理/示例/解决方案)

菩提树下的杨过: ZooKeeper 笔记(1) 安装部署及hello world ZooKeeper 笔记(2) 监听数据变化 ZooKeeper 笔记(3) 实战应用之【统一配置管理】 ZooKeeper 笔记(4) 实战应用之【消除单点故障】...

easonjim
2017/09/05
0
0
Rmote学习笔记-zyh

RMI的概念: RMI(Remote Method Invocation)远程方法调用是一种计算机之间利用远程对象互相调用实现双方通讯的一种通讯机制。使用这种机制,某一台计算机上的对象可以调用另外一台计算机上的...

颖辉小居
2016/11/13
15
0

没有更多内容

加载失败,请刷新页面

加载更多

CQRS与AXON

CQRS 看了蛮多文章,只会CRUD,却不懂CQRS,CQRS是遵循DDD思想而产生的一种模式,Command and Query Responsibility Segregation 命令与查询隔离。查询就直接通过正常的模式service调dao层。...

无极之岚
30分钟前
4
0
OSChina 周三乱弹 —— 欢迎你来做产品经理

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @巴拉迪维 :10多次劲歌金曲获奖,更多叱咤歌坛排名,黎明才应该是四大天王之首,只可惜拍的电影太少。单曲循环一个多月的歌,力荐 《无名份的...

小小编辑
45分钟前
90
5
500行代码,教你用python写个微信飞机大战

这几天在重温微信小游戏的飞机大战,玩着玩着就在思考人生了,这飞机大战怎么就可以做的那么好,操作简单,简单上手。 帮助蹲厕族、YP族、饭圈女孩在无聊之余可以有一样东西让他们振作起来!...

上海小胖
今天
8
0
关于AsyncTask的onPostExcute方法是否会在Activity重建过程中调用的问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/XG1057415595/article/details/86774575 假设下面一种情况...

shzwork
今天
7
0
object 类中有哪些方法?

getClass(): 获取运行时类的对象 equals():判断其他对象是否与此对象相等 hashcode():返回该对象的哈希码值 toString():返回该对象的字符串表示 clone(): 创建并返此对象的一个副本 wait...

happywe
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部