文章目录
一.服务端启动流程分析
1.四大必须属性
从一个最简单的服务端Demo看起
- NIOServer
public class NIOServer {
public static void main(String[] args) {
ServerBootstrap serverBootstrap = new ServerBootstrap(); // 启动引导器
NioEventLoopGroup bossGroup = new NioEventLoopGroup(); // 监听组
NioEventLoopGroup workerGroup = new NioEventLoopGroup(); // 工作组
serverBootstrap.group(bossGroup, workerGroup) // 指定线程模型:监听组和工作组
.channel(NioServerSocketChannel.class) // IO模型:NIO模式
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
// 初始化channel:连接后的读写逻辑
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(String.format("服务端接收到消息:%s", msg));
}
});
}
}).bind(8000); //启动端口
}
}
要启动Netty服务端,必须要指定四类必须属性,分别是:
- 线程模型
- IO模型
- 连接后的读写逻辑
- 启动端口
2.启动引导器:serverBootstrap
所有的服务都在启动器上进行注册和配置。
3.线程模型:bossGroup和workerGroup
创建了两个NioEventLoopGroup
,这两个对象可以看做是传统IO编程模型的两大线程组,bossGroup
表示监听端口,accept
新连接的线程组,workerGroup
表示处理每一条连接的数据读写的线程组。bossGroup接收完连接,会交给workerGroup去处理。最后通过.group(bossGroup, workerGroup)
去指定线程模型。
4.IO模型:NioServerSocketChannel和OioServerSocketChannel
通过.channel(NioServerSocketChannel.class)
来指定 IO 模型,当然,这里也有其他的选择,如果你想指定 IO 模型为 BIO,那么这里配置上OioServerSocketChannel.class
类型即可,通常不会指定BIO为线程模型,因为Netty的优势就在于NIO。
5.连接后读写逻辑
.childHandler()
方法,给这个引导类创建一个ChannelInitializer
,这里主要就是定义后续每条连接的数据读写,业务处理逻辑。也可新创建一个类并继承ChannelInboundHandlerAdapter
来实现读写逻辑。
6.引导器其他方法参数
-
childHandler():给引导类创建ChannelInitializer定义后续每条连接的数据读写,业务处理逻辑,泛型参数NioSocketChannel是Netty对NIO类型的连接的抽象,而NioServerSocketChannel也是对NIO类型的连接的抽象
-
bind():异步地返回ChannelFuture,给ChannelFuture添加监听器GenericFutureListener,在GenericFutureListener的operationComplete方法里面监听端口是否绑定成功
-
childHandler():用于指定处理新连接数据的读写处理逻辑,handler()用于指定在服务端启动过程中的一些逻辑
-
attr():给服务端的channel即NioServerSocketChannel指定一些自定义属性,通过channel.attr()取出该属性,给NioServerSocketChannel维护一个map
-
childAttr():给每一条连接指定自定义属性,通过channel.attr()取出该属性
-
childOption():给每条连接设置一些TCP底层相关的属性:
ChannelOption.SO_KEEPALIVE表示是否开启TCP底层心跳机制,true为开启 ChannelOption.SO_REUSEADDR表示端口释放后立即就可以被再次使用,因为一般来说,一个端口释放后会等待两分钟之后才能再被使用 ChannelOption.TCP_NODELAY表示是否开始Nagle算法,true表示关闭,false表示开启,通俗地说,如果要求高实时性,有数据发送时就马上发送,就关闭,如果需要减少发送次数减少网络交互就开启
-
option():给服务端channel设置一些TCP底层相关的属性:
ChannelOption.SO_BACKLOG表示系统用于临时存放已完成三次握手的请求的队列的最大长度,如果连接建立频繁,服务器处理创建新连接较慢,适当调大该参数
二.客户端启动流程分析
从一个最简单的Netty客户端Demo看起
- NIOClient
public class NIOClient {
public static void main(String[] args) throws InterruptedException {
Bootstrap bootstrap = new Bootstrap(); // 引导启动类
NioEventLoopGroup group = new NioEventLoopGroup(); // 工作组
bootstrap
.group(group) // 添加线程模型
.channel(NioSocketChannel.class) // 添加IO模型
.handler(new ChannelInitializer<SocketChannel>() {// 添加连接后的读写逻辑
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringEncoder());
}
});
Channel channel = bootstrap.connect("127.0.0.1", 8000).channel(); // 建立连接
while (true) {
String message = String.format("HelloWorld From %s", new SimpleDateFormat("hh:mm:ss").format(new Date()));
// 通过连接向服务端发送消息
channel.writeAndFlush(message);
Thread.sleep(2000);
}
}
}
对于客户端的启动来说,和服务端的启动类似,依然需要线程模型、IO 模型,以及连接后业务处理逻辑和连接主机与端口,这4大参数,启动流程如下:
其他方法与服务端类似
来源:CSDN
作者:ARong.
链接:https://blog.csdn.net/pbrlovejava/article/details/104159817