Netty简介
来源:互联网 发布:巴蒂斯图塔巅峰数据 编辑:程序博客网 时间:2024/05/29 14:50
Netty
Netty是基于Java NIO的网络应用框架。
Netty是一个NIO client-server(客户端-服务器)框架,使用Netty可以快速开发网络应用,例如服务器和客户端协议。Netty提供一种新的方式来开发网络应用程序,这种新的方式是的它很容易使用和有很强的扩展性。
Netty的内部实现是复杂的,但是Netty提供了简单一用的api从网络处理代码中解耦业务逻辑。
Netty是完全基于NIO实现的,所以整个Netty都是非阻塞的。
网络应用程序通常需要较高的可扩展性,无论是Netty还是其他基于JAVA NIO的框架,都会提供可扩展性的解决方案。Netty中一个关键组成部分是它的异步特性,本章将讨论同步(阻塞)和异步(非阻塞)的IO来说明为什么使用异步代码来解决扩展性问题以及如何使用异步。
在学习Netty之前,先回顾一下NIO的通信步骤:
- 创就绪建ServerSocketChannel,为它配置非阻塞模式。
- 绑定监听,配置TCP参数,录入backlog大小
- 创建一个独立的IO线程,用于轮询多路复用器Selector
- 创建Selector,将之前创建的ServerSocketChannel注册到Selector上,并设置监听标志位SelectionKEY.ACCEPT
- 启动IO线程,在循环体中执行Selector.select()方法,轮询就绪的通道。
- 当轮询到了处于就绪的通道时,需要进行判断操作位,如果是ACCEPT状态,说明是新的客户端接入,则调用accept方法接受新的客户端。
- 设置新接入客户端的一些参数,如非阻塞、并将其通道继续注册到Selector之中,设置监听标志位等。
- 如果轮询的通道操作位是READ,则进行读取,构造Buffer对象等。
- 更细节的还有数据没法送完成继续发送的问题。
Netty实现通信的步骤:
- 创建两个NIO线程组,一个专门用于网络事件处理(接受客户端的连接),另一个则进行网络通信读写。
- 创建一个ServerBootstrap对象,配置Netty的一系列参数,例如接受传出数据的缓存大小等等。
- 创建一个实际处理数据的类ChannelInitalizer,进行初始化的准备工作,比如设置接受传出数据的字符集、格式、已经实际处理数据的接口。
- 绑定端口,执行同步阻塞方法等待服务器启动即可。
Client.java
public class Client { public static void main(String[] args) throws InterruptedException { 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",8765).sync();// ChannelFuture cf2 = b.connect("127.0.0.1",8764).sync(); //buf cf1.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty".getBytes())); Thread.sleep(1000); cf1.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty".getBytes())); Thread.sleep(1000); cf1.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty".getBytes()));// cf1.channel().flush(); cf1.channel().closeFuture().sync(); workgroup.shutdownGracefully(); }}
Server.java
public class Server { public static void main(String[] args) throws InterruptedException { //1 第一个线程组用于接受client端连接的 NioEventLoopGroup bossGroup = new NioEventLoopGroup(); //2 第二个线程组用于实际的业务处理操作的 NioEventLoopGroup workerGroup = new NioEventLoopGroup(); //3 创建一个辅助类Bootstrap,就是对我们的Server进行一系列的配置 ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup,workerGroup)//把两个工作线程组加入进来 .channel(NioServerSocketChannel.class)//使用NIOServerSocketChannel这种类型的通道 .childHandler(new ChannelInitializer<SocketChannel>() {//使用childHandler绑定具体的事件处理器 @Override protected void initChannel(SocketChannel sc) throws Exception { sc.pipeline().addLast(new ServerHandler()); } }) /** * 服务器端TCP内核模块维护两个队列,我们称之为A和B * 客户端向服务器端connect的时候 会发送带有SYN标志的包(第一次握手) * 服务器收到客户端发来的SYN时,向客户端发送SYN ACK确认(第二次握手) * 此时TCP内核模块将客户端连接加入A队列中,然后服务器收到客户端发来的ACK时(第三次握手) * TCP内核模块将客户端从A队列移动到B队列,连接完成,应用程序的accept会返回。 * 也就是说accept从B队列中取出完成三次握手的连接 * A队列和B队列的长度之和是backlog。当A、B队列的长度之和大于backlog时,新连接将会被TCP内核拒绝 * 所以,如果backlog过小,可能会出现accept速度跟不上,A、B队列满了,导致新的客户无法连接。 * 要注意的是:backlog对程序的连接数并无影响,backlog影响的知识还没有被accept取出的连接。 */ //设置TCP缓冲区 .option(ChannelOption.SO_BACKLOG, 128) //保持连接 .childOption(ChannelOption.SO_KEEPALIVE, true); //绑定指定的端口进行监听 ChannelFuture f = b.bind(8765).sync();// ChannelFuture f2 = b.bind(8764).sync(); //将服务器阻塞 f.channel().closeFuture().sync();// f2.channel().closeFuture().sync(); bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); }}
ServerHandler.java
public class ServerHandler extends ChannelHandlerAdapter{ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {// ((ByteBuf)msg).release(); try{ //do sth 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 = "我是反馈的消息"; ChannelFuture channelFuture = ctx.channel().writeAndFlush(Unpooled.copiedBuffer("Hi Client!".getBytes())); //写完后断开连接// channelFuture.addListener(ChannelFutureListener.CLOSE);// ctx.channel().flush(); }finally{ ReferenceCountUtil.release(msg); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}
ClientHandler.java
public class ClientHandler extends ChannelHandlerAdapter{ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {// ((ByteBuf)msg).release(); try{ //do sth 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); //写给服务器端 /*String response = "我是反馈给服务器的消息"; ctx.channel().writeAndFlush(Unpooled.copiedBuffer("999".getBytes()));*/ }finally{ //读数据必须释放 ReferenceCountUtil.release(msg); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}
0 0
- Netty简介
- Netty简介
- Netty简介
- Netty ChannelBuffer 简介
- Java NIO netty 简介
- netty简介 demo
- Java Netty简介
- netty入门简介
- netty简介及使用
- Netty in action—Netty简介
- netty (http框架) 简介
- Netty简介、架构、机制、特性
- Netty的入门 - IO简介
- Netty初学之一:简介-HellWord-讲解
- 基于netty的消息队列StormMQ简介
- Netty
- Netty
- Netty
- 使用Dom4j解析xml文件
- itchat4j -- 用Java扩展个人微信号的能力
- pointPolygonTest多边形检测
- 面试用算法复杂度总结
- SIFT算法详解与应用
- Netty简介
- solr hard soft提交均衡设置,并取消手动提交
- php基础知识 9.数组
- 【C】五大排序算法
- 网络协议
- MATLAB中imfill()函数解释
- Liferay DXP Soy portlet系列(一) 创建SOY portlet
- MySQL 重温SQL——行转列,列转行
- HDU 5901 Count primes (大素数模板题)