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 快速入门的更多相关文章

  1. Web Api 入门实战 (快速入门+工具使用+不依赖IIS)

    平台之大势何人能挡? 带着你的Net飞奔吧!:http://www.cnblogs.com/dunitian/p/4822808.html 屁话我也就不多说了,什么简介的也省了,直接简单概括+demo ...

  2. SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提升)

     SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=>提升,5个Demo贯彻全篇,感兴趣的玩才是真的学) 官方demo:http://www.asp.net/si ...

  3. 前端开发小白必学技能—非关系数据库又像关系数据库的MongoDB快速入门命令(2)

    今天给大家道个歉,没有及时更新MongoDB快速入门的下篇,最近有点小忙,在此向博友们致歉.下面我将简单地说一下mongdb的一些基本命令以及我们日常开发过程中的一些问题.mongodb可以为我们提供 ...

  4. 【第三篇】ASP.NET MVC快速入门之安全策略(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  5. 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  6. Mybatis框架 的快速入门

    MyBatis 简介 什么是 MyBatis? MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结果 ...

  7. grunt快速入门

    快速入门 Grunt和 Grunt 插件是通过 npm 安装并管理的,npm是 Node.js 的包管理器. Grunt 0.4.x 必须配合Node.js >= 0.8.0版本使用.:奇数版本 ...

  8. 【第一篇】ASP.NET MVC快速入门之数据库操作(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  9. 【第四篇】ASP.NET MVC快速入门之完整示例(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

随机推荐

  1. Handling Event

    [Handling Event] 1.React events are named using camelCase 2.You must call preventDefault explicitly ...

  2. oracle 创建包体的一些问题

    1. PLS-00201:必须声明标识符'A1' PLS-00304: 如果没有说明, 则无法编译'A1'主体 解决办法: 用sysdba身份 把A1包的执行权限给这个用户. 举例: 1.C:\Use ...

  3. 常用的jquerymobil 站点

    http://www.jqmapi.com/api1.2/ Jquery Mobile 中文API站 https://codiqa.com/demo   jquerymobil UI编辑器 https ...

  4. http协议与常见状态码

    什么是http: http是属于应用层(基于tcp的连接方式)的面向对象的协议,是计算机通过网络通信的规则,使得浏览器向web服务器请求信息和服务 http协议特点: http是一种无状态协议(对食物 ...

  5. vue使用全局element-ui组件

    安装loader模块: cnpm install style-loader -D cnpm install css-loader -D cnpm install file-loader -D   安装 ...

  6. Python+Selenium学习--简单对象定位

    场景 测试对象的定位和操作是webdriver的核心内容,其中操作又是建立在定位的基础之上,因此对象定位就越发显得重要了. 定位对象的目的一般有下面几种 操作对象 获得对象的属性,如获得测试对象的cl ...

  7. wiper

    wiper - 必应词典 美['waɪpər]英['waɪpə(r)] n.手绢儿:搌布:揩布:(汽车风挡上的)雨刷器 网络刮水器:雨刮器:拭雨器 变形复数:wipers:

  8. java编程 求和

    用java编程,实现字符串强制类型转化成整数型,用到Integer.parseInt(),可以把字符串强制转换成整数 结果截图

  9. Wannafly挑战赛13 B:Jxc军训(逆元)

    题目描述 在文某路学车中学高一新生军训中,Jxc正站在太阳下站着军姿,对于这样的酷热的阳光,Jxc 表示非常不爽. Jxc将天空看做一个n*n的矩阵,此时天上有m朵云,这些云会随机分布在m个不同的位置 ...

  10. python第三方库requests简单介绍

    一.发送请求与传递参数 简单demo: import requests r = requests.get(url='http://www.itwhy.org') # 最基本的GET请求 print(r ...