netty1 快速入门
Netty是一个高性能、异步事件驱动的网路通信框架 ,由于精力有限,本人并没有对其源 码做了特别细致的研究。如果下面的内容有错误或不严谨的地方,也请大家指正和谅解。
Netty的线程模型是Reactor主从模型的变种,去掉了线程池,使用串行化实现。
Reactor主从模型如下图所示

(mainReactor负责监听server socket,accept新连接;并将建立的socket分派给subReactor。
subReactor负责多路分离已连接的socket,读写网络数据,对业务处理功能,其扔给worker线程池完成。通常,subReactor个数上可与CPU个数等同)
Netty中Reactor模式的参与者主要有下面一些组件:
Selector
EventLoopGroup/EventLoop
ChannelPipeline
Selector即为NIO中提供的多路复用器,这里不再阐述。
EventLoopGroup/EventLoop
EventLoopGroup是一组EventLoop的抽象,在Netty服务器编程中我们需要BossEventLoopGroup和WorkerEventLoopGroup两个EventLoopGroup来进行工作。通常一个服务端口即一个ServerSocketChannel对应一个Selector和一个EventLoop线程,也就是说BossEventLoopGroup的线程数参数为1。BossEventLoop主要负责接收客户端的连接并
将SocketChannel交给WorkerEventLoopGroup来进行处理。
ChannelPipeline
ChannelPipeline在Reactor模式中担任请求处理器的角色,通过调用相关的handler进行相对应的处理。
以下是第一个入门程序
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 Server {
public static void main(String[] args) throws Exception {
// 1 第一个线程组 是用于接收Client端连接的
EventLoopGroup bossGroup = new NioEventLoopGroup();
// 2 第二个线程组 是用于实际的业务处理操作的
EventLoopGroup workerGroup = new NioEventLoopGroup();
// 3 创建一个辅助类Bootstrap,就是对我们的Server进行一系列的配置
ServerBootstrap bbootStarp = new ServerBootstrap();
// 把俩个工作线程组加入进来
bbootStarp.group(bossGroup, workerGroup)
// 指定使用NioServerSocketChannel这种类型的通道
.channel(NioServerSocketChannel.class)
// 一定要使用 childHandler 去绑定具体的 事件处理器
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel sc) throws Exception {
sc.pipeline().addLast(new ServerHandler());
}
});
// 绑定指定的端口 进行监听
ChannelFuture channelFuture = bbootStarp.bind(8765).sync(); // 让其不关闭
channelFuture.channel().closeFuture().sync();
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully(); }
}
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil; public class ServerHandler extends ChannelInboundHandlerAdapter { //处理客户端发送过来的数据
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try {
ByteBuf byteBuffer = (ByteBuf) msg;
byte[] data = new byte[byteBuffer.readableBytes()];
byteBuffer.readBytes(data);
String sData = new String(data,"utf-8");
System.out.println("server "+sData); //写操作完成以后就断开连接
ctx.writeAndFlush(Unpooled.copiedBuffer("888".getBytes())).addListener(ChannelFutureListener.CLOSE); } finally {
ReferenceCountUtil.release(msg);
}
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
} }
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
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 Client { public static void main(String[] args) throws Exception { EventLoopGroup workgroup = new NioEventLoopGroup(); Bootstrap boot = new Bootstrap(); boot.group(workgroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel sc) throws Exception {
sc.pipeline().addLast(new ClientHandler());
}
}); ChannelFuture channelFuture = boot.connect("127.0.0.1", 8765).sync(); //buf
channelFuture.channel().writeAndFlush(Unpooled.copiedBuffer("777".getBytes())); channelFuture.channel().closeFuture().sync();
workgroup.shutdownGracefully(); }
}
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil; public class ClientHandler extends ChannelInboundHandlerAdapter { @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try {
// do something \
ByteBuf buf = (ByteBuf) msg;
byte[] data = new byte[buf.readableBytes()];
buf.readBytes(data);
String request = new String(data, "utf-8");
System.out.println("Client: " + request); } finally {
// 如果没有调用write或者writeAndFlush 需要手动释放msg
ReferenceCountUtil.release(msg);
}
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
可以看到,server 和client的创建连接或者发送请求的代码的都是相对固定的,实际开发中 我们专注写handler 就好。
netty1 快速入门的更多相关文章
- Web Api 入门实战 (快速入门+工具使用+不依赖IIS)
平台之大势何人能挡? 带着你的Net飞奔吧!:http://www.cnblogs.com/dunitian/p/4822808.html 屁话我也就不多说了,什么简介的也省了,直接简单概括+demo ...
- SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提升)
SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=>提升,5个Demo贯彻全篇,感兴趣的玩才是真的学) 官方demo:http://www.asp.net/si ...
- 前端开发小白必学技能—非关系数据库又像关系数据库的MongoDB快速入门命令(2)
今天给大家道个歉,没有及时更新MongoDB快速入门的下篇,最近有点小忙,在此向博友们致歉.下面我将简单地说一下mongdb的一些基本命令以及我们日常开发过程中的一些问题.mongodb可以为我们提供 ...
- 【第三篇】ASP.NET MVC快速入门之安全策略(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- Mybatis框架 的快速入门
MyBatis 简介 什么是 MyBatis? MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结果 ...
- grunt快速入门
快速入门 Grunt和 Grunt 插件是通过 npm 安装并管理的,npm是 Node.js 的包管理器. Grunt 0.4.x 必须配合Node.js >= 0.8.0版本使用.:奇数版本 ...
- 【第一篇】ASP.NET MVC快速入门之数据库操作(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- 【第四篇】ASP.NET MVC快速入门之完整示例(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
随机推荐
- Structured streaming
Structured streaming是spark 2.0以后新增的用于实时处理的技术.与spark streaming不同的是,Structured streaming打开了数据源到数据落地之间的 ...
- zabbix主动监测客户端设置
主动/被动模式 主动模式和被动模式的区别一开始我也非常模糊,其实这是zabbix的两种工作方式,是相对于zabbix的agent端来说的,定义为: 主动模式:zabbix的agent端,也就是客户端, ...
- centos 7 redis-4.0.11 主从
redis-master:192.168.199.223 redis-slave: 192.168.199.224 cd /opt wget http://download.redis.io/rele ...
- this.$router
router.go(n)这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n) router.push(location)想要导航 ...
- 201. Bitwise AND of Numbers Range (Bit)
Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND(按位与) of all nu ...
- glove
glove - 必应词典 美[ɡlʌv]英[ɡlʌv] v.给戴手套:作…的手套 n.(分手指的)手套 网络分指手套:拳套:棒球之爱 变形复数:gloves:现在分词:gloving:过去分词:glo ...
- ASP.Net MVC 在ajax接收controller返回值为Json数据
首先,再次回忆一下ajax的标准用法:(这张图写的比较详细了)(转) 页面部分ajax代码: $.ajax({ url: "/Home/Login?account=&q ...
- 关于客户端调用后台事件__doPostBack函数的使用
1. 动态添加生成的控件:Asp.net开发网站,最喜欢用的就是使用服务器控件,在后台进行数据操作了,你无需再去管get还是post提交,也不用去理会form,只需在后台服务器控件的事件中就可以对 ...
- PHP如何处理yyyyMMddHHmmssSSSZ?
PHP如何处理yyyyMMddHHmmssSSSZ? 更新: 2016-01-05 12:45 作者: wecandoitforev PHP编程中,时间,日期的应用是必不可少的.有一种日期格式:yyy ...
- 转)服务器安装部署ESXI6.0
1.制作一个ESXI6.0的系统安装盘 2.服务器启动后加载VMware ESXi 6.0的ISO文件,开始安装. 3.ESXi引导装入程序,VMware ESXi引导过程,在屏幕上方显示的版本号.内 ...