Netty客户端发起连接过程注意点

使用Netty创建客户端的时候, 和创建服务端类似, 也需要经过创建-初始化-注册这三步, 最后一步也最重要就是连接操作, io.netty.bootstrap.Bootstrap#connect(java.net.SocketAddress)

创建就是创建NioSocketChannel, 同时也会创建unsafe,pipeline,config等. 还会设置一个感兴趣的SelectionKey.OP_READ 读事件属性, 此时也仅仅是把OP_READ保存到一个属性上.

初始化就是给channel设置一些option和attribute.

注册就是将channel注册到对应的NioEventLoop的selector上.

这个连接操作会调用到JDK的channel.connect方法, 然而连接操作实际就是向服务端发启TCP三次握手, 握手是有网络延时的, 而Netty是非阻塞的网络框架. Netty调用connect方法, 发起连接之后就返回了, 但是它会向channel中注册一个感兴趣的连接事件.
源码位置: io.netty.channel.socket.nio.NioSocketChannel#doConnect
在这里插入图片描述等到三次握手完成之后, Netty客户端就会监听到连接事件. (Netty底层会有一个IO线程, 一直轮询着外部的事件)

源码位置: io.netty.channel.nio.NioEventLoop#processSelectedKey(java.nio.channels.SelectionKey, io.netty.channel.nio.AbstractNioChannel)
在这里插入图片描述

io.netty.channel.DefaultChannelPipeline.HeadContext#channelActive

io.netty.channel.DefaultChannelPipeline.HeadContext#readIfIsAutoRead

io.netty.channel.DefaultChannelPipeline.HeadContext#read

io.netty.channel.nio.AbstractNioChannel#doBeginRead

protected void doBeginRead() throws Exception {
	final SelectionKey selectionKey = this.selectionKey;
	if (!selectionKey.isValid()) {
		return;
	}

	readPending = true;

	final int interestOps = selectionKey.interestOps();
	if ((interestOps & readInterestOp) == 0) {
		// 设置之前保存起来的事件, 例如OP_READ
		selectionKey.interestOps(interestOps | readInterestOp);
	}
}
    

再经过以上四个主要方法, 最后就会设置感兴趣的OP_READ事件了. 这样客户端才可以读取数据.

【总结】
客户端在向服务器发起连接请求的时候, 由于网络等原因, 连接不会马上成功, Netty是非阻塞框架. 因此在发起连接之后就返回了, 同时设置一个感兴趣的OPCONNECT事件, 等三次握手成功之后, Netty监听到OPCONNECT事件, 然后才会把设置之前的OP_READ事件, 这个时候客户端才可以读取网络数据.


个人站点
语雀

公众号

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值