美文网首页
Netty客户端发起连接过程注意点

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

作者: 书唐瑞 | 来源:发表于2021-03-27 21:54 被阅读0次

使用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

图片.png

等到三次握手完成之后, Netty客户端就会监听到连接事件. (Netty底层会有一个IO线程, 一直轮询着外部的事件)

源码位置: io.netty.channel.nio.NioEventLoop#processSelectedKey(java.nio.channels.SelectionKey, io.netty.channel.nio.AbstractNioChannel)

图片.png
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事件, 这个时候客户端才可以读取网络数据.

相关文章

网友评论

      本文标题:Netty客户端发起连接过程注意点

      本文链接:https://www.haomeiwen.com/subject/pbnyhltx.html