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. JMeter学习(十二)分布式部署(转载)

    转载自 http://www.cnblogs.com/yangxia-test Jmeter 是java 应用,对于CPU和内存的消耗比较大,因此,当需要模拟数以千计的并发用户时,使用单台机器模拟所有 ...

  2. CentOS rpm

    rpm命令是RPM软件包的管理工具.rpm原本是Red Hat Linux发行版专门用来管理Linux各项套件的程序,由于它遵循GPL规则且功能强大方便,因而广受欢迎.逐渐受到其他发行版的采用.RPM ...

  3. 贪吃蛇Controller Java实现(二)

    package cn.tcc.snake.Controller; import java.awt.Point;import java.awt.event.KeyAdapter;import java. ...

  4. UVA-10054.The Necklace(欧拉回路)解题报告

    2019-02-09-21:55:23 原题链接 题目描述: 给定一串珠子的颜色对,每颗珠子的两端分别有颜色(用1 - 50 之间的数字表示,对每颗珠子的颜色无特殊要求),若两颗珠子的连接处为同种颜色 ...

  5. HDU4522 湫湫系列故事——过年回家

    传送门:点我 中文题面. 思路:拿spfa对卧铺和硬铺分别跑spfa,然后找两个的最短路.体感堆优化的dij也可以,不过spfa跑跑就过去了.有个细节是最后得用long long 存数据,其他的没啥. ...

  6. width多少,超过了用....表示

    maxWidth:'140px',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'

  7. sql查询 !='' 和 is not null的区别

    select * from table where a is not null 会把有内容的和内容为空的都查出来而select * from table where a != '' 只会把有内容的查出 ...

  8. BadgeView 圆形数字提醒 购物车常用

    实际上BadgeView这个类就是继承TextView的.很多TextView中设置字体的方法都适用于BadgeView. 1. setTargetView(View) --> 设置哪个控件显示 ...

  9. abp ef codefirst Value cannot be null. Parameter name: connectionString

    错误原因是abp生成的项目是mvc类型的,但在使用时,选择了vue去开发,所以在abp上重新生成了一个vue项目,把原有的mvc项目给删掉了,没有将新生成的vue类型的项目的文件覆盖掉原有的mvc其他 ...

  10. vue2.0后台系统

    参考网址: http://www.cnblogs.com/linxin/p/6509897.html