ServerBootstrap介绍
ServerBootstrap也继承AbstractBootstrap,所以ServerBootstrap和Bootstrap的结构是差不多的,但是ServerBootstrap负责初始化netty服务器,并且开始监听端口的socket请求。
EchoServer
先看看Netty自带的EchoServer例子:
public final class EchoServer {
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
public static void main(String[] args) throws Exception {
// Configure the server.
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
//利用这个方法设置EventLoopGroup,Boos线程和Worker线程就是同一个
//b.group(bossGroup)
//利用这个方法设置EventLoopGroup,Boos线程和Worker线程就是两个
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.TCP_NODELAY, true)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
//p.addLast(new LoggingHandler(LogLevel.INFO));
p.addLast(new EchoServerHandler());
}
});
b.bind(PORT).syncUninterruptibly();
} finally {
// Shut down all event loops to terminate all threads.
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
ServerBootstrap的boss线程和worker线程
对于接触过socket的同学来说,我们都知道服务端会绑定一个端口,然后服务端监听这个端口,如果有客户端的请求,服务器会给响应,并且会给客户端发送数据.
对于ServerBootstrap来说,处理socket连接的线程就是Boos线程,就是ServerBootstrap的group方法的第一个参数.服务端接受了socket连接求后,会产生一个channel(一个打开的socket对应一个打开的channel),并把这个channel交给Worker线程来处理,,就是ServerBootstrap的group方法的第二个参数,boss线程则继续处理socket的请求。如果客户端数目不是很多的情况,Boos线程和Worker线程可以是同一个。
ServerBootstrap和Bootstrap的不同之处
1)ServerBootstrap继承AbstractBootstrap了,但是自己本身还有额外的属性。
private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap<ChannelOption<?>, Object>();
private final Map<AttributeKey<?>, Object> childAttrs = new LinkedHashMap<AttributeKey<?>, Object>();
private volatile EventLoopGroup childGroup;
private volatile ChannelHandler childHandler;
2)之前说设置完Bootstrap运行所需要的参数之后,调用的是connect方式,ServerBootstrap会调用bind方法.
3)ServerBootstrap设置EventLoopGroup,需要设置两个,也可以设置一个,设置一个就意味着接受连接和处理channel都是同一个EventLoopGroup.下面是ServerBootstrap代码中的片段。
/**
* Specify the {@link EventLoopGroup} which is used for the parent (acceptor) and the child (client).
*/
@Override
public ServerBootstrap group(EventLoopGroup group) {
return group(group, group);
}
/**
* Set the {@link EventLoopGroup} for the parent (acceptor) and the child (client). These
* {@link EventLoopGroup}'s are used to handle all the events and IO for {@link ServerChannel} and
* {@link Channel}'s.
*/
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
super.group(parentGroup);
if (childGroup == null) {
throw new NullPointerException("childGroup");
}
if (this.childGroup != null) {
throw new IllegalStateException("childGroup set already");
}
this.childGroup = childGroup;
return this;
}
3)我们知道ServerBootstrap有一个option,但是还有一个childOption。option是给Boos线程设置的,childOption是给Worker线程设置的。设置的参数的值同Bootstrap。
3)我们知道ServerBootstrap有一个handler,但是还有一个childHandler。handler在ServerBootstrap初始化时就会执行,而childHandler会在客户端成功connect后才执行,这是两者的区别。
ServerBootstrap执行流程
图片来源:http://blog.youkuaiyun.com/wwh578867817/article/details/47099505