架构师养成记--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才是执行具体任务的地方. 总体流程应该是这样的: 具体一点,代 ...
随机推荐
- Qt's Undo Framework
Overview of Qt's Undo Framework Introduction Qt's Undo Framework is an implementation of the Command ...
- MyBatis 实用篇(二)配置文件
MyBatis 实用篇(二)配置文件 一.全局配置 全局配置:http://www.mybatis.org/mybatis-3/zh/configuration.html <?xml versi ...
- linux git server 简易搭建 (ssh访问)
git的服务器搭建,如果无需权限控制,仅团队内部使用,初始化一个服务器仓库,其他人通过ssh访问这个文件夹即可.如需复杂的管理,建议使用gitlab. yum install git -y id gi ...
- Oracle GoldenGate 二、配置和使用
Oracle GoldenGate 二.配置和使用 配置和使用GoldenGate的步骤 1 在源端和目标端配置数据库支持GoldenGate 2 在源端和目标端创建和配置GoldenGate实例 3 ...
- Oracle物化视图的一般使用
普通视图和物化视图根本就不是一个东西,说区别都是硬拼到一起的,首先明白基本概念,普通视图是不存储任何数据的,他只有定义,在查询中是转换为对应的定义SQL去查询,而物化视图是将数据转换为一个表,实际存储 ...
- Codeforces 766C Mahmoud and a Message 2017-02-21 13:57 62人阅读 评论(0) 收藏
C. Mahmoud and a Message time limit per test 2 seconds memory limit per test 256 megabytes input sta ...
- eclipse中不能找到dubbo.xsd报错”cvc-complex-type.2.4.c“的 两种解决方法
配置dubbo环境过程中的xml文件,安装官网的demo配置好后,出错: "Description Resource Path Location Type cvc-complex-type. ...
- [翻译]Writing Custom Common Controls 编写自定义控件
摘要:介绍如何编写自定义的控件,用在报表的窗体上(如Edit,Button等) Writing Custom Common Controls 编写自定义控件 FastReport contains ...
- [Elixir006]CSV(Comma-separated values)处理
1. CSV文件格式是什么 CSV有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本).纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数 ...
- 杭州.Net 相关大公司,希望对大家有帮助
本人目前大四,还在实习.北京工作辞职后,打算回杭州看看.发现杭州的大公司相对北京好少啊,招.Net相关的公司就更少了... (我认为刚毕业生还是去大公司比较靠谱,一方面也是实力的体现)大学生,而且之前 ...