一、Netty4客户端启动代码
public static void main(String[] args) throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();
b.group(group).channel(NioSocketChannel.class);
b.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
pipeline.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
pipeline.addLast("handler", new TcpClientHandler());
}
});
b.option(ChannelOption.SO_KEEPALIVE, true);
Channel channel = b.connect("127.0.0.1", 9999).sync().channel();
}
二、具体解析
1.初始化Bootstrap,创建一个线程池NioEventLoopGroup, b.handler设置自身的处理器ChannelHandler handler,服务端使用的b.childHandler是设置的是与客户端进行交互的通道的处理器,自身的处理器是ServerBootstrapAcceptor,设置channel为NioSocketChannel,设置通道的网络选项,常设置的有超时时间,是否禁用Nagle优化的TCP_NODELAY,这个参数的意思是,当某一次的发送数据量很小的话,他不会立即发送给对方,等待一段时间或者当需要发送的数据量达到窗口的大小时才会正式发送给对方,实时性要求比较高的业务一般都会禁用这个优化。
2.Bootstrap开始连接服务端connect
public ChannelFuture connect(String inetHost, int inetPort) {
return connect(new InetSocketAddress(inetHost, inetPort));
}
和服务端代码很类似,初始化NioSocketChannel注册最后连接
private ChannelFuture doConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
final ChannelFuture regFuture = initAndRegister();
final Channel channel = regFuture.channel();
final ChannelPromise promise = channel.newPromise();
if (regFuture.isDone()) {
doConnect0(regFuture, channel, remoteAddress, localAddress, promise);
}
return promise;
}
initAndRegister操作,NioSocketChannel,socket为SelectorProvider.provider().openSocketChannel()
public NioSocketChannel(Channel parent, SocketChannel socket) {
super(parent, socket);
config = new NioSocketChannelConfig(this, socket.socket());
}
他的父类是AbstractNioByteChannel,而不是服务端对应的AbstractNioMessageChannel,保存读后面会设置监听事件