Bootstrap
-
option方法:设置ChannelOption,其将被应用到每个新创建的Channel的ChannelConfig。这些选项将会通过bind()或者connect()方法设置到Channel,不管哪个先被调用。不管哪个先被调用。这个方法在Channel已经被创建后再调用不会有任何的效果。支持的ChannelOption取决于使用的Channel类型。
-
attr方法:指定新创建的Channel的属性值。这些属性值是通过bind()或者connect()方法设置到Channel的,具体取决于谁最先被调用。这个方法在Channel被创建后将不会有任何效果。
ServerBootstrap
- option
- childOption
- attr
- childAttr
- handler
- childHandler
从Channel中引导客户端
(大致就是服务端的ChannelHandler需要建立一个建立一个Bootstra与另一个服务器链接)
假设服务器正在处理一个客户端的请求,这个请求需要服务器充当第三方系统的客户端。当一个应用程序(如一个代理服务器)必须要和组织现有的系统(如Web服务或者数据库)集成时,就可能发生这种情况。在这种情况下,将需要从已经被接受的子Channel中引导一个客户端Channel。
可以创建新的Bootstrap实例,但是这不是最高效的解决方案,因为它要求你为每个新创建的客户端Channel定义另一个EventLoop。这会产生额外的线程,以及在已被接受的子Channel和护短端Channel之间交换数据时不可避免的上下文切换(可以理解这部分)。
一个更好的解决方法是:通过将已被接受的子Channel的EventLoop传递给Bootstrap的group()方法来共享该EventLoop。因为分配给EventLoop的所有Channel都使用同一个线程,所以这避免了额外的线程创建,以及上下文切换。
(可以,比较容易理解)
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
|
BootstrapUtils.runServer(new SimpleChannelInboundHandler<ByteBuf>() {
ChannelFuture connectChannel;
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
Bootstrap bootstrap = new Bootstrap()
.group(ctx.channel().eventLoop())
.channel(NioSocketChannel.class)
.handler(new SimpleChannelInboundHandler<ByteBuf>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
System.out.println("Received data");
}
});
bootstrap.connect(new InetSocketAddress("www.baidu.com", 80));
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
if (connectChannel.isDone()) {
// do something with the data
}
}
});
|
编写Netty应用程序的一个一般准则:尽可能地重用EventLoop,以减少线程创建所带来的开销。
ChannelOption与Attribute
可用的ChannelOption包括了底层连接的详细信息,如keep-alive、超时属性、缓冲设置。
Netty应用程序通常与组织的专有软件集成在一起,而像Channel这样的组件可能甚至会在正常的Netty生命周期之外被使用。在某些常用的属性和数据不可用时,Netty提供了属性抽象(一个由Channel和引导类提供的集合)以及属性Key抽象(一个用于插入和获取属性值的泛型类)。使用这些工具,便可以安全地将任何类型的数据项与客户端和服务端Channel(包含ServerChannel的子Channel)相关联了。
(不太理解)
考虑一个用户跟踪用户和Channel质检的关系的服务器应用程序。这可以通过将用户id存储为Channel的一个属性来完成。类似的技术可以被用来基于用户的id将消息路由给用户,或者关闭活动较少的Channel。
(不是太理解,我为什么不用userId到Channel的Map呢?)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
final AttributeKey<Integer> id = AttributeKey.valueOf("ID");
Bootstrap bootstrap = new Bootstrap()
.group(new NioEventLoopGroup())
.channel(NioSocketChannel.class)
.handler(new SimpleChannelInboundHandler<ByteBuf>() {
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
Integer integer = ctx.channel().attr(id).get();
// do something
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
System.out.println("Received data");
}
})
.option(ChannelOption.SO_KEEPALIVE, true)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
.attr(id, 123456);
bootstrap.connect().syncUninterruptibly();
|
引导数据报
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
Bootstrap bootstrap = new Bootstrap()
.group(new OioEventLoopGroup())
.channel(OioDatagramChannel.class)
.handler(new SimpleChannelInboundHandler<DatagramPacket>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
// do something
}
});
bootstrap.bind().addListener((ChannelFutureListener) future -> {
});
|