Netty Bootstrap

———— 4.1.72.Final
words: 440    views:    time: 2min

Bootstrap在Netty中相当于一个组织者的角色,负责初始化装配和启动。

server
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
EventLoopGroup acceptGroup = new NioEventLoopGroup();
EventLoopGroup handleGroup = new NioEventLoopGroup();
ServerBootstrap serverBoot = new ServerBootstrap();
serverBoot.group(acceptGroup, handleGroup).channel(NioServerSocketChannel.class);
serverBoot.option(ChannelOption.SO_BACKLOG, 1024);
serverBoot.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel channel) throws Exception {
channel.pipeline().addLast(new ChannelInboundHandlerAdapter(){
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
System.out.println(msg);
ctx.writeAndFlush("helle, client");
}
});
}
});

try {
ChannelFuture channelFuture = serverBoot.bind(8181).sync();
channelFuture.channel().closeFuture().sync();
} finally {
acceptGroup.shutdownGracefully();
handleGroup.shutdownGracefully();
}
client
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Bootstrap clientBoot = new Bootstrap();
EventLoopGroup handleGroup = new NioEventLoopGroup();
clientBoot.group(handleGroup);
clientBoot.channel(NioSocketChannel.class);
clientBoot.option(ChannelOption.TCP_NODELAY, true);
clientBoot.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel channel) throws Exception {
channel.pipeline().addLast(new ChannelInboundHandlerAdapter(){
@Override
public void channelActive(ChannelHandlerContext ctx) {
ctx.writeAndFlush("hello, server");
}

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
System.out.println(msg);
}
});
}
});

try {
ChannelFuture channelFuture = clientBoot.connect("127.0.0.1", 8181).sync();
channelFuture.channel().closeFuture().sync();
} finally {
handleGroup.shutdownGracefully();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
channel = channelFactory.newChannel();
init(channel);
} catch (Throwable t) {
if (channel != null) {
// channel can be null if newChannel crashed (eg SocketException("too many open files"))
channel.unsafe().closeForcibly();
// as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
}
// as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
}

ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}

// If we are here and the promise is not failed, it's one of the following cases:
// 1) If we attempted registration from the event loop, the registration has been completed at this point.
// i.e. It's safe to attempt bind() or connect() now because the channel has been registered.
// 2) If we attempted registration from the other thread, the registration request has been successfully
// added to the event loop's task queue for later execution.
// i.e. It's safe to attempt bind() or connect() now:
// because bind() or connect() will be executed *after* the scheduled registration task is executed
// because register(), bind(), and connect() are all bound to the same thread.
return regFuture;
}


参考: