Netty4.0学习笔记系列之一:Server与Client的通讯
http://blog.csdn.net/u013252773/article/details/21046697
本文是学习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代码如下:
- package com.guowl.testserver;
- import io.netty.bootstrap.ServerBootstrap;
- import io.netty.channel.ChannelFuture;
- import io.netty.channel.ChannelInitializer;
- import io.netty.channel.ChannelOption;
- import io.netty.channel.EventLoopGroup;
- import io.netty.channel.nio.NioEventLoopGroup;
- import io.netty.channel.socket.SocketChannel;
- import io.netty.channel.socket.nio.NioServerSocketChannel;
- public class HelloServer {
- public void start(int port) throws Exception {
- EventLoopGroup bossGroup = new NioEventLoopGroup();
- EventLoopGroup workerGroup = new NioEventLoopGroup();
- try {
- ServerBootstrap b = new ServerBootstrap();
- b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
- .childHandler(new ChannelInitializer<SocketChannel>() {
- @Override
- public void initChannel(SocketChannel ch)
- throws Exception {
- // 注册handler
- ch.pipeline().addLast(new HelloServerInHandler());
- }
- }).option(ChannelOption.SO_BACKLOG, 128)
- .childOption(ChannelOption.SO_KEEPALIVE, true);
- ChannelFuture f = b.bind(port).sync();
- f.channel().closeFuture().sync();
- } finally {
- workerGroup.shutdownGracefully();
- bossGroup.shutdownGracefully();
- }
- }
- public static void main(String[] args) throws Exception {
- HelloServer server = new HelloServer();
- server.start(8000);
- }
- }
2、HelloServerInHandler代码如下:
- package com.guowl.testserver;
- import io.netty.buffer.ByteBuf;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.channel.ChannelInboundHandlerAdapter;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- // 该handler是InboundHandler类型
- public class HelloServerInHandler extends ChannelInboundHandlerAdapter {
- private static Logger logger = LoggerFactory
- .getLogger(HelloServerInHandler.class);
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg)
- throws Exception {
- logger.info("HelloServerInHandler.channelRead");
- ByteBuf result = (ByteBuf) msg;
- byte[] result1 = new byte[result.readableBytes()];
- // msg中存储的是ByteBuf类型的数据,把数据读取到byte[]中
- result.readBytes(result1);
- String resultStr = new String(result1);
- // 接收并打印客户端的信息
- System.out.println("Client said:" + resultStr);
- // 释放资源,这行很关键
- result.release();
- // 向客户端发送消息
- String response = "I am ok!";
- // 在当前场景下,发送的数据必须转换成ByteBuf数组
- ByteBuf encoded = ctx.alloc().buffer(4 * response.length());
- encoded.writeBytes(response.getBytes());
- ctx.write(encoded);
- ctx.flush();
- }
- @Override
- public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
- ctx.flush();
- }
- }
3、HelloClient代码如下:
- package com.guowl.testserver;
- import io.netty.bootstrap.Bootstrap;
- import io.netty.channel.ChannelFuture;
- import io.netty.channel.ChannelInitializer;
- import io.netty.channel.ChannelOption;
- import io.netty.channel.EventLoopGroup;
- import io.netty.channel.nio.NioEventLoopGroup;
- import io.netty.channel.socket.SocketChannel;
- import io.netty.channel.socket.nio.NioSocketChannel;
- public class HelloClient {
- public void connect(String host, int port) throws Exception {
- EventLoopGroup workerGroup = new NioEventLoopGroup();
- try {
- Bootstrap b = new Bootstrap();
- b.group(workerGroup);
- b.channel(NioSocketChannel.class);
- b.option(ChannelOption.SO_KEEPALIVE, true);
- b.handler(new ChannelInitializer<SocketChannel>() {
- @Override
- public void initChannel(SocketChannel ch) throws Exception {
- ch.pipeline().addLast(new HelloClientIntHandler());
- }
- });
- // Start the client.
- ChannelFuture f = b.connect(host, port).sync();
- // Wait until the connection is closed.
- f.channel().closeFuture().sync();
- } finally {
- workerGroup.shutdownGracefully();
- }
- }
- public static void main(String[] args) throws Exception {
- HelloClient client = new HelloClient();
- client.connect("127.0.0.1", 8000);
- }
- }
4、HelloClientIntHandler代码如下:
- package com.guowl.testserver;
- import io.netty.buffer.ByteBuf;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.channel.ChannelInboundHandlerAdapter;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- public class HelloClientIntHandler extends ChannelInboundHandlerAdapter {
- private static Logger logger = LoggerFactory.getLogger(HelloClientIntHandler.class);
- // 接收server端的消息,并打印出来
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- logger.info("HelloClientIntHandler.channelRead");
- ByteBuf result = (ByteBuf) msg;
- byte[] result1 = new byte[result.readableBytes()];
- result.readBytes(result1);
- System.out.println("Server said:" + new String(result1));
- result.release();
- }
- // 连接成功后,向server发送消息
- @Override
- public void channelActive(ChannelHandlerContext ctx) throws Exception {
- logger.info("HelloClientIntHandler.channelActive");
- String msg = "Are you ok?";
- ByteBuf encoded = ctx.alloc().buffer(4 * msg.length());
- encoded.writeBytes(msg.getBytes());
- ctx.write(encoded);
- ctx.flush();
- }
- }
通过上面简单的实例可以发现:
1、在没有任何encoder、decoder的情况下,Netty发送接收数据都是按照ByteBuf的形式,其它形式都是不合法的。
2、接收发送数据操作都是通过handler实现的,handler在netty中占据了非常重要的位置。
3、netty的handler是基于事件触发的,例如当client连接server成功后,client中的HelloClientIntHandler的channelActive方法会自动调用。
Netty4.0学习笔记系列之一:Server与Client的通讯的更多相关文章
- Netty4.0学习笔记系列之四:混合使用coder和handler
Handler如何使用在前面的例子中已经有了示范,那么同样是扩展自ChannelHandler的Encoder和Decoder,与Handler混合后又是如何使用的?本文将通过一个实际的小例子来展示它 ...
- Netty4.0学习笔记系列之二:Handler的执行顺序(转)
http://blog.csdn.net/u013252773/article/details/21195593 Handler在netty中,无疑占据着非常重要的地位.Handler与Servlet ...
- Netty4.0学习笔记系列之三:构建简单的http服务(转)
http://blog.csdn.net/u013252773/article/details/21254257 本文主要介绍如何通过Netty构建一个简单的http服务. 想要实现的目的是: 1.C ...
- Netty4.0学习笔记系列之二:Handler的执行顺序
Handler在netty中,无疑占据着非常重要的地位.Handler与Servlet中的filter很像,通过Handler可以完成通讯报文的解码编码.拦截指定的报文.统一对日志错误进行处理.统一对 ...
- Apache Ignite 学习笔记(三): Ignite Server和Client节点介绍
在前两篇文章中,我们把Ignite集群当做一个黑盒子,用二进制包自带的脚本启动Ignite节点后,我们用不同的客户端连接上Ignite进行操作,展示了Ignite作为一个分布式内存缓存,内存数据库的基 ...
- SQLServer学习笔记系列2
一.写在前面的话 继上一次SQLServer学习笔记系列1http://www.cnblogs.com/liupeng61624/p/4354983.html以后,继续学习Sqlserver,一步一步 ...
- 步步为营 SharePoint 开发学习笔记系列总结
转:http://www.cnblogs.com/springyangwc/archive/2011/08/03/2126763.html 概要 为时20多天的sharepoint开发学习笔记系列终于 ...
- Redis 学习笔记系列文章之 Redis 的安装与配置 (一)
1. 介绍 Redis is an open source (BSD licensed), in-memory data structure store, used as database, cach ...
- WebService学习笔记系列(二)
soap(简单对象访问协议),它是在http基础之上传递xml格式数据的协议.soap协议分为两个版本,soap1.1和soap1.2. 在学习webservice时我们有一个必备工具叫做tcpmon ...
随机推荐
- GDB踪函数的完整调用过程 及原理
http://www.lenky.info/archives/2013/02/2202 Breakpoint , .so. (gdb) bt # .so. # .so. # .so. # .so. # ...
- block没那么难(一):block的实现
本系列博文总结自<Pro Multithreading and Memory Management for iOS and OS X with ARC> block 顾名思义就是代码块,将 ...
- htmlentities() 函数
Definition and Usage定义和用法 The htmlentities() function converts characters to HTML entities.htmlentit ...
- sqlserver 时间 格式化
0 或 100 (*) 默认值 mon dd yyyy hh:miAM(或 PM) 1 101 美国 mm/dd/yyyy ...
- sql根据'/'截取最后的字符串
filpath字段值:/DataFile/UpLoad/Logo/NoPhoto.jpg select filpath,REVERSE((SUBSTRING(REVERSE(FilPath),0,CH ...
- VS2015 Cordova Ionic移动开发(五)
一.创建侧边菜单和导航项目 1.使用VS创建一个Ionic空项目,同时创建一个Ionic SideMenu和Ionic Tabs项目.将SideMenu和Tabs项目里的templates和js文件合 ...
- java '相等'的比较.
我们知道对于操作符 "==",如果比较的是原生类型(primitive type),表示的是 '值本身'是否相等;而对于引用类型(reference type),表示的是 '对象的 ...
- poj1828
poj1828 [问题的描述]是这样的:程序猿的近亲 猴子(......)最近在进行王位争夺站. 题中使用二维坐标轴上的点(x,y)来代表猴子所占有的位置, 每只猴子占有一个坐标点.并且一个坐标点上面 ...
- 使用Xcode插件,让iOS开发更加便捷
在iOS开发过程中,写注释是一项必不可少的工作.这不仅有助于自己对代码整理回顾,而且提高了代码的可读性,让代码维护变得容易.但是,写注释又是一项枯燥的工作.我们浪费了大量的时间在输入/*,*,*/这样 ...
- CSS3美化表单控件
表单的默认控件在不同的浏览器中的样式不同,用户体验很差.用CSS3可以实现表单控件的美化,可以提供更好的用户体验.不足之处就是浏览器的兼容性问题. 一.下拉控件 效果图: 下拉控件的布局结构: < ...