架构师养成记--19.netty
一、Netty初步
为什么选择Netty?
和NIO比较,要实现一个通信要简单得很多,性能很好。分布式消息中间件、storm、Dubble都是使用Netty作为底层通信。
Netty5.0要求jdk1.6以上。
http://netty.io
二、编码步骤
创建两个Nio线程组,一个事件处理,一个网络读写通信
创建一个ServerBootStrap,配置Netty参数;
创建实际处理的ChannelInitializer,进行初始化的准备工作,比如设置接收传出的字符集,格式,已经实际处理数据接口
绑定端口执行同步阻塞方法等待服务器端启动。
并发编程网 http://ifeve.com/netty5-user-guide
三、代码
服务端
- 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;
- /**
- * Created by sgm on 2017/1/28.
- */
- public class Server {
- public static void main(String []args) throws InterruptedException {
- /**
- * EventLoopGroup 事件组,不同的事件组处理不同的协议,这里使用NioEventLoopGroup来处理Tcp协议
- * 第一个事件循环组用来接收客户端信息,通常被称作boss,boos接收到信息后注册到worker上
- * 第二个事件循环组做实际的业务处理
- */
- EventLoopGroup bossGroup = new NioEventLoopGroup();
- EventLoopGroup workerGroup = new NioEventLoopGroup();
- /**
- * 引导,对server进行一系列的配置
- */
- ServerBootstrap b = new ServerBootstrap();
- //将boss和worker关联起来
- b.group(bossGroup,workerGroup)
- .channel(NioServerSocketChannel.class)//使用的通道类型
- .childHandler(new ChannelInitializer<SocketChannel>() {
- @Override
- protected void initChannel(SocketChannel socketChannel) throws Exception {
- socketChannel.pipeline().addLast(new ServerHandler());
- }
- })//添加serverHandler,绑定具体的事件处理器
- /**
- * 当客户端向客户端发送请求会带一个信号,服务器端返回一个信号并且将客户端的链接信息加入队列A中,
- * 服务器再收到一个客户端的信号并且将客户端的信息从队列A移动到队列B中;
- * 队列A和队列B的长度之和就是BACKLOG,如果大于了BACKLOG,tcp内核就会拒绝链接,BACKLOG只会影响到没有被accept取出的链接
- */
- .option(ChannelOption.SO_BACKLOG,128)
- .option(ChannelOption.SO_KEEPALIVE,true);//保持连接
- ChannelFuture cf = b.bind(9876).sync();//绑定端口进行监听,异步的监听
- cf.channel().closeFuture().sync();//阻塞
- workerGroup.shutdownGracefully();
- bossGroup.shutdownGracefully();
- }
- }
- import io.netty.buffer.ByteBuf;
- import io.netty.buffer.Unpooled;
- import io.netty.channel.ChannelHandlerAdapter;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.util.ReferenceCountUtil;
- /**
- * Created by Administrator on 2017/1/28.
- */
- public class ServerHandler extends ChannelHandlerAdapter{
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- try {
- //do something msg
- ByteBuf buf = (ByteBuf)msg;
- byte[] data = new byte[buf.readableBytes()];
- buf.readBytes(data);
- String request = new String(data, "utf-8");
- System.out.println("Server: " + request);
- //写给客户端
- String response = "我是反馈的信息";
- ctx.writeAndFlush(Unpooled.copiedBuffer("888".getBytes()));
- }finally {
- ReferenceCountUtil.release(msg);//有上一句话,即ctx.writeAndFlush(),这里可以不关闭
- }
- }
- @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 b = new Bootstrap();
- b.group(workgroup)
- .channel(NioSocketChannel.class)
- .handler(new ChannelInitializer<SocketChannel>() {
- @Override
- protected void initChannel(SocketChannel sc) throws Exception {
- sc.pipeline().addLast(new ClientHandler());
- }
- });
- ChannelFuture cf1 = b.connect("127.0.0.1", 9876).sync();
- //buf
- cf1.channel().writeAndFlush(Unpooled.copiedBuffer("777".getBytes()));
- cf1.channel().closeFuture().sync();
- workgroup.shutdownGracefully();
- }
- }
- import io.netty.buffer.ByteBuf;
- import io.netty.buffer.Unpooled;
- import io.netty.channel.ChannelHandlerAdapter;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.util.ReferenceCountUtil;
- public class ClientHandler extends ChannelHandlerAdapter {
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- try {
- //do something msg
- 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 {
- ReferenceCountUtil.release(msg);
- }
- }
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
- cause.printStackTrace();
- ctx.close();
- }
- }
架构师养成记--19.netty的更多相关文章
- 架构师养成记--21.netty编码解码
背景 作为网络传输框架,免不了哟啊传输对象,对象在传输之前就要序列化,这个序列化的过程就是编码过程.接收到编码后的数据就需要解码,还原传输的数据. 代码 工厂类 import io.netty.han ...
- 架构师养成记--20.netty的tcp拆包粘包问题
问题描述 比如要发ABC DEFG HIJK 这一串数据,其中ABC是一个包,DEFG是一个包,HIJK是一个包.由于TCP是基于流发送的,所以有可能出现ABCD EFGH 这种情况,那么ABC和D就 ...
- 架构师养成记--22.客户端与服务器端保持连接的解决方案,netty的ReadTimeoutHandler
概述 保持客户端与服务器端连接的方案常用的有3种 1.长连接,也就是客户端与服务器端一直保持连接,适用于客户端比较少的情况. 2.定时段连接,比如在某一天的凌晨建立连接,适用于对实时性要求不高的情况. ...
- 架构师养成记--35.redis集群搭建
前记:redis哨兵经验之谈.哨兵做主从切换可能要花费一两秒,这一两秒可能会丢失很多数据.解决方法之一是在java代码中做控制,try catch 到 链接断开的异常就sleep 一两秒钟再conti ...
- 架构师养成记--15.Disruptor并发框架
一.概述 disruptor对于处理并发任务很擅长,曾有人测过,一个线程里1s内可以处理六百万个订单,性能相当感人. 这个框架的结构大概是:数据生产端 --> 缓存 --> 消费端 缓存中 ...
- 架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock
ReentrantLock 有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级. this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决 ...
- 架构师养成记--12.Concurrent工具类CyclicBarrier和CountDownLatch
java.util.concurrent.CyclicBarrier 一组线程共同等待,直到达到一个公共屏障点. 举个栗子,百米赛跑中,所有运动员都要等其他运动员都准备好后才能一起跑(假如没有发令员) ...
- 架构师养成记--11.Executor概述
常用方法 Executors.newFiexdPool(int nThreads);固定线程数量的线程池: Executors.newSingleThreadExecutor();单个线程的线程池: ...
- 架构师养成记--10.master-worker模式
master-worker模式是一种并行计算模式,分为master进程和worker进程两个部分,master是担任总管角色,worker才是执行具体任务的地方. 总体流程应该是这样的: 具体一点,代 ...
随机推荐
- Multiply Strings大整数乘法
[抄题]: 以字符串的形式给定两个非负整数 num1 和 num2,返回 num1 和 num2 的乘积. [暴力解法]: 时间分析: 空间分析: [思维问题]: 还要找到结果中第一位不等于0的数再添 ...
- cmake条件编译
CMake的条件编译基于if elseif endif.3.0版本具体语法如下 if(expression) # then section. COMMAND1(ARGS ...) COMMAND2(A ...
- vbs执行系统命令
首先说明一下,我的所有代码都是vbscript,jscript我没有研究过,不过我想也差不多. 关于最基础的语法比如变量的申明,分支,循环,函数的调用,等等这些我就不讲了,不懂得自己看一下. 1.我们 ...
- Mybatis之是如何执行你的SQL的(SQL执行过程,参数解析过程,结果集封装过程)
Myabtis的SQL的执行是通过SqlSession.默认的实现类是DefalutSqlSession.通过源码可以发现,selectOne最终会调用selectList这个方法. @Overrid ...
- C++笔记16之const的用法总结
const主要是为了程序的健壮型,减少程序出错. 最基本的用法: const int a=100; b的内容不变,b只能是100也就是声明一个int类型的常量(#define b =100) int ...
- 作业3:PSP记录耗时情况
PSP2.1 Personal Software Process Stage Time planning 计划 10min Estimate 估计这个任务多久完成 150min Developing ...
- 如何注册GitHub
一.个人介绍 姓名:张志龙 学号:1413042026 班级:网工141 爱好:宅物 能力:c++编程 二.注册 注册GitHub其实很简单 首先我们要做的是打开官网 www.github.com(如 ...
- vue实现首页导航切换不同路由的方式(二)【使用vuex实现的】
<nav> <!-- 导航栏 --> <div class="indexNavOut"> <div class="indexNa ...
- python signal
在了解了Linux的信号基础之 后,Python标准库中的signal包就很容易学习和理解.signal包负责在Python程序内部处理信号,典型的操作包括预设信号处理函数,暂 停并等待信号,以及定时 ...
- 10-09 Linux的文件系统介绍以及各种设备的说明
Linux的文件编程 linux文件管理系统分为3部分:与文件管理有关的软件,被管理的文件,实施文件管理需要的数据结构 用C语言建立,打开,关闭文件,向文件写入和读出数据等. Linux文件系统简介 ...