Netty快速入门
2018-02-22 18:32
399 查看
Netty快速入门
异步非阻塞IO什么是Netty
Netty 是一个基于 JAVA NIO 类库的异步通信框架,它的架构特点是:异步非阻塞、基于事件驱动、高性能、高可靠性和高可定制性。Netty应用场景
1.分布式开源框架中dubbo、Zookeeper,RocketMQ,底层rpc通讯使用就是netty。2.游戏开发中,底层使用netty通讯。
为什么选择netty
因为可以解决NIO代码复杂问题,以及有更好的容错机制!那么为什么不建议开发者直接使用JDK的NIO类库进行开发?
1) NIO的类库和API繁杂,使用麻烦,你需要熟练掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等;
2) 需要具备其它的额外技能做铺垫 。
例如:熟悉Java多线程编程,因为NIO编程涉及到Reactor模式,你必须对多线程和网路编程非常熟悉,才能编写出高质量的NIO程序;
3) 可靠性能力补齐,工作量和难度都非常大。
例如:客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常码流的处理等等,NIO编程的特点是功能开发相对容易,但是可靠性能力补齐工作量和难度都非常大;
4) JDK NIO的BUG。
例如:臭名昭著的epoll bug,它会导致Selector空轮询,最终导致CPU 100%。官方声称在JDK1.6版本的update18修复了该问题,但是直到JDK1.7版本该问题仍旧存在,只不过该bug发生概率降低了一些而已,它并没有被根本解决。
代码示例
Maven坐标
<dependency> <groupId>io.netty</groupId> <artifactId>netty</artifactId> <version>3.10.5.Final</version> </dependency>
Netty服务器端
public class NettyServer { public static void main(String[] args) { //创建服务类对象 ServerBootstrap serverBootstrap = new ServerBootstrap(); //创建两个线程池,分别为监听端口,监听NIO ExecutorService boos = Executors.newCachedThreadPool(); ExecutorService worker = Executors.newCachedThreadPool(); //设置工程,并把两个线程池加入其中 serverBootstrap.setFactory(new NioServerSocketChannelFactory(boos,worker)); //设置管道工程 serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = Channels.pipeline(); //将数据转换为String类型 pipeline.addLast("decoder",new StringDecoder()); pipeline.addLast("encoder",new StringEncoder()); pipeline.addLast("serverHandler",new ServerHandler()); return pipeline; } }); //绑定端口号 serverBootstrap.bind(new InetSocketAddress(8080)); System.out.println("Netty服务器端已经启动..."); } } class ServerHandler extends SimpleChannelHandler{ /** * 通道关闭的时候触发 */ @Override public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { System.out.println("通道关闭的时候触发:channelClosed"); } /** * 必须是连接已经建立,关闭通道的时候才会触发 */ @Override public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { System.out.println("必须是连接已经建立,关闭通道的时候才会触发:channelDisconnected"); } /** * 捕获异常 */ @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { System.out.println("捕获异常:exceptionCaught"); } /** * 接受消息 */ @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { System.out.println("服务器端接受到客户端的消息:"+e.getMessage()); //回复内容 ctx.getChannel().write("您好,主人暂时不在,有事请留言!!!"); } }
Netty客户端
public class NettyClient { public static void main(String[] args) { System.out.println("Netty客户端已经启动..."); //创建服务类对象 ClientBootstrap clientBootstrap = new ClientBootstrap(); //创建两个线程池,分别为监听端口,监听NIO ExecutorService boos = Executors.newCachedThreadPool(); ExecutorService worker = Executors.newCachedThreadPool(); //设置工程,并把两个线程池加入其中 clientBootstrap.setFactory(new NioClientSocketChannelFactory(boos,worker)); //设置管道工程 clientBootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = Channels.pipeline(); //将数据转换为String类型 pipeline.addLast("decoder",new StringDecoder()); pipeline.addLast("encoder",new StringEncoder()); pipeline.addLast("clientHandler",new ClientHandler()); return pipeline; } }); //连接服务端 ChannelFuture connect = clientBootstrap.connect(new InetSocketAddress("127.0.0.1", 8080)); Channel channel = connect.getChannel(); System.out.println("Client Start"); Scanner scanner = new Scanner(System.in); while (true){ System.out.println("请输入内容:"); String str = scanner.next(); channel.write(str); } } } class ClientHandler extends SimpleChannelHandler { /** * 通道关闭的时候触发 */ @Override public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { System.out.println("通道关闭的时候触发:channelClosed"); } /** * 必须是连接已经建立,关闭通道的时候才会触发 */ @Override public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { System.out.println("必须是连接已经建立,关闭通道的时候才会触发:channelDisconnected"); } /** * 捕获异常 */ @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { System.out.println("捕获异常:exceptionCaught"); } /** * 接受消息 */ @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { System.out.println("服务器端向客户端回复内容:"+e.getMessage()); //回复内容 // ctx.getChannel().write("您好,主人暂时不在,有事请留言!!!"); } }
运行结果
服务器端:客户端:
相关文章推荐
- Netty 快速入门系列 - Chapter 3 Netty5.x【第九讲】 - 单客户多Client 重连
- Netty 快速入门系列 - Chapter 6 自定义数据协议【第十四讲】ByteBuffer 和 ChannelBuffers
- Netty 快速入门系列 - Chapter 1 传统OIO与NIO - NIO 【第二讲】
- Netty 快速入门系列 - Chapter 4 Netty心跳【第十讲】 - IdleStateHandler学习
- Netty 快速入门系列 - Chapter 3 Netty5.x【第六讲】 -Netty5 案例
- Netty 快速入门系列 - Chapter 6 自定义数据协议【第十五讲】自定义方法Serializer
- Netty 快速入门系列 - Chapter 8 数据包协议【第二十一讲】FrameDecoder 讲解
- Netty 快速入门系列 - Chapter 5 Netty之序列化【第十一讲】 Protocol buff
- 网络应用框架Netty快速入门
- Netty 快速入门系列 - Chapter 7 数据包协议【第十六讲】数据传输问题
- Netty 快速入门系列 - Chapter 7 数据包协议【第十九讲】解决方案-粘包分包原理
- Netty 快速入门系列 - Chapter 8 数据包协议【第二十二讲】Socket攻击及防护
- Netty 快速入门系列 - Chapter 3 Netty5.x【第七讲】 - Channel线程安全?
- Netty 快速入门系列 - Chapter 7 数据包协议【第十七讲】解决方案- 分割符 及 长度+数据
- Netty 快速入门系列 - Chapter 2 Netty3.x 【第四讲】 - 基本原理
- 网络应用框架Netty快速入门
- Netty 快速入门系列 - Chapter 3 Netty5.x【第八讲】 - Client 重连
- Netty 快速入门系列 - Chapter 2 Netty3.x 【第五讲】 - 源码讲解
- Netty 快速入门系列 - Chapter 5 Netty之序列化【第十二讲】 Java Serializable
- Netty 快速入门系列 - Chapter 7 数据包协议【第十八讲】解决方案-经典协议包结构