Netty是快速开发高性能,高扩展性的网络服务器和客户端提供的异步框架。目标有:
-
快速轻松开发,不仅能快速轻松开发tcp,udp程序,还能开发ftp,http外的其他应用层协议。
-
高性能,高扩展,基于Java的NIO设计了优秀的Reactor模式实现。
这里选择Netty4版本。依赖如下:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.113.Final</version>
</dependency>
以一个简单的服务开始Netty的学习之旅。用Netty实现一个Discard服务:丢弃客户端发送的数据,也不向客户端发送数据。
public static void startServer(int port) {
ServerBootstrap serverBootstrap = new ServerBootstrap();
// 监听客户端并接受连接轮询组
NioEventLoopGroup bossEventLoppGroup = new NioEventLoopGroup();
//工作轮询组
NioEventLoopGroup workEventLoppGroup = new NioEventLoopGroup();
try {
// 1、设置轮询组
ChannelFuture channelFuture = serverBootstrap.group(bossEventLoppGroup, workEventLoppGroup)
// 2、设置NIO类型通道
.channel(NioServerSocketChannel.class)
// 3、设置监听端口
.localAddress(new InetSocketAddress("localhost",port))
// 4、设置通道参数
.childOption(ChannelOption.SO_KEEPALIVE, true)
// 5、装配子通道流水线
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
nioSocketChannel.pipeline().addLast(new DiscardHandle());
}
})
// 6、绑定服务器
.bind();
ChannelFuture sync = channelFuture.sync();
System.out.println("服务器启动成功,绑定端口"+sync.channel().localAddress());
// 7、等待通道异步关闭
sync.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 8 、释放资源
bossEventLoppGroup.shutdownGracefully();
workEventLoppGroup.shutdownGracefully();
}
}
//ChannelInboundHandlerAdapter是ChannelInboundHandler的默认实现
public class DiscardHandle extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf) msg;
System.out.println("收到消息如下");
try {
while (byteBuf.isReadable()) {
System.out.print((char) byteBuf.readByte());
}
System.out.println();
} finally {
ReferenceCountUtil.release(byteBuf);
}
}
}
ServerBootstrap负责Netty组件的组装,配置,Netty服务器或客户端的启动。也可以不用ServerBootstrap,而由自己负责这些工作。
1、第一步创建了两个反映器轮询组。回顾下Reactor模式,这里的轮询组实现了Reactor模式中Reactor线程的工作。第一个轮询组叫作boss轮询组,负责监听并连接客户端,也叫做“包工头”,第二个轮询组叫做工作轮询组,负责数据的传输及处理。也可以直接用一个轮询组。反映器轮询组与Reactor模式中的Reactor线程不同,一个轮询组中有一个线程池,里面的每个线程相当于Reactor模式中的Reactor线程。
2、设置通道的类型。Netty不止支持NIO,也支持BIO,还可以配置为OioServerSocketChannel。
3、设置监听端口。
4、设置通道的参数。注意第4步,第5步的方法名,有child
。为什么要这么命名?因为有父子通道的概念。在Linux系统中,NioServerSocketChannel包装了Linux系统中的文件描述符,这个文件描述符负责监听客户端的连接。NioSocketChannel也包装了Linux系统中的文件描述符,负责数据传输及处理。NioServerSocketChannel叫做NioSocketChannel的父通道,NioSocketChannel叫NioServerSocketChannel的子通道。注意第4步,第5步的方法名设置的都是子通道中的属性。所以要有child。
这些参数一般都是与TCP协议相关的。
SO_KEEPALIVE:是否开启TCP的心跳机制,true为连接保持心跳,false为关闭。
SO_SNDBUF:TCP在内核中的发送缓冲区大小
SO_RCVBUF:TCP在内核中的接收缓冲区大小
TCP_NODELAY:是否开启Nagle算法,为true,关闭Nagle算法,马上发送数据。为false,开启Nagle算法,等数据积累缓冲区在发送。
SO_BACKLOG:TCP三次握手时接收连接的队列长度。
SO_LINGER:-1表示socket.close调用后立即返回,操作系统会将缓冲区的数据全部发送。0表示socket.close调用后立即返回,操作系统会放弃发送缓冲区的数据。非0的整数表示socket.close调用后被阻塞直到超时(数字表示超时时间)发送缓冲区数据,若超时,接收端收到错误。
5、装配子通道的Pipleline。服务器接受客户端的连接后,会调用此方法设置channel的Pipeline,Pipeline是个双向连表,里面保存了ChannelInboundHandler(入站处理器,主要负责读取)和ChannelOutboundHandler(出站处理器,主要负责写入)。
入站处理器是从前往后执行,如果后面还有入站处理器,将IO事件交给下一个入站处理器处理。否则将结束。
出站处理器是从后往前执行。
6、绑定服务器,并启动。注意观察。bind方法的返回值是ChannelFuture,,是异步的,调用了sync让它同步执行绑定成功。
7、获取closeFuture关闭通道,并等待监听通道关闭。
8、释放资源。轮询组内的线程,Selector,子通道都会被关闭。
标签:Netty,Reactor,轮询,TCP,初识,通道,客户端 From: https://www.cnblogs.com/shigongp/p/18445052