91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Netty客戶端接入流程NioSocketChannel怎么創建

發布時間:2022-03-28 09:21:29 來源:億速云 閱讀:151 作者:小新 欄目:開發技術

這篇文章主要為大家展示了“Netty客戶端接入流程NioSocketChannel怎么創建”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“Netty客戶端接入流程NioSocketChannel怎么創建”這篇文章吧。

NioSocketChannel的創建

回到上一小節的read()方法

public void read() {
    //必須是NioEventLoop方法調用的, 不能通過外部線程調用
    assert eventLoop().inEventLoop();
    //服務端channel的config
    final ChannelConfig config = config();
    //服務端channel的pipeline
    final ChannelPipeline pipeline = pipeline();
    //處理服務端接入的速率
    final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
    //設置配置
    allocHandle.reset(config);
    boolean closed = false;
    Throwable exception = null;
    try {
        try {
            do {
                //創建jdk底層的channel
                //readBuf用于臨時承載讀到鏈接
                int localRead = doReadMessages(readBuf);
                if (localRead == 0) {
                    break;
                }
                if (localRead < 0) {
                    closed = true;
                    break;
                }
                //分配器將讀到的鏈接進行計數
                allocHandle.incMessagesRead(localRead);
                //連接數是否超過最大值
            } while (allocHandle.continueReading());
        } catch (Throwable t) {
            exception = t;
        }
        int size = readBuf.size();
        //遍歷每一條客戶端連接
        for (int i = 0; i < size; i ++) {
            readPending = false;
            //傳遞事件, 將創建NioSokectChannel進行傳遞
            //最終會調用ServerBootstrap的內部類ServerBootstrapAcceptor的channelRead()方法
            pipeline.fireChannelRead(readBuf.get(i));
        }
        readBuf.clear();
        allocHandle.readComplete();
        pipeline.fireChannelReadComplete();
        //代碼省略
    } finally {
        //代碼省略
    }
}

我們繼續剖析int localRead = doReadMessages(readBuf)這一部分邏輯

我們首先看readBuf

private final List<Object> readBuf = new ArrayList<Object>();

這里只是簡單的定義了一個ArrayList, doReadMessages(readBuf)方法就是將讀到的鏈接放在這個list中, 因為這里是NioServerSocketChannel所以這走到了NioServerSocketChannel的doReadMessage()方法

跟到doReadMessage()方法中:

protected int doReadMessages(List<Object> buf) throws Exception {
    //根據當前jdk底層的serverSocketChannel拿到jdk底層channel
    SocketChannel ch = javaChannel().accept();
    try {
        if (ch != null) {
            //封裝成一個NioSokectChannel扔到buf中
            buf.add(new NioSocketChannel(this, ch));
            return 1;
        }
    } catch (Throwable t) {
        //代碼省略
    }
    return 0;
}

jdk底層相關的內容

首先根據jdk的ServerSocketChannel拿到jdk的Channel, 熟悉Nio的小伙伴應該不會陌生

封裝成一個NioSokectChannel扔到Readbuf中

這里的NioSocketChannel是對jdk底層的SocketChannel的包裝, 我們看到其構造方法傳入兩個參數, this代表當前NioServerSocketChannel, ch代表jdk的SocketChannel

我們跟到NioSocketChannel的構造方法中:

public NioSocketChannel(Channel parent, SocketChannel socket) {
    super(parent, socket);
    config = new NioSocketChannelConfig(this, socket.socket());
}

這里看到調用了父類構造方法, 傳入兩個參數, parent代表創建自身channel的, NioServerSocketChannel, socket代表jdk底層的socketChannel

跟到父類構造方法中

protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) { 
    super(parent, ch, SelectionKey.OP_READ);
}

其中SelectionKey.OP_READ代表其監聽事件是讀事件

繼續跟父類的構造方法:

protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
    super(parent);
    this.ch = ch;
    this.readInterestOp = readInterestOp;
    try {
        //設置為非阻塞
        ch.configureBlocking(false);
    } catch (IOException e) {
        //代碼省略
    }
}

這里初始化了自身成員變量ch, 就是jdk底層的SocketChannel, 并初始化了自身的監聽事件readInterestOp, 也就是讀事件

ch.configureBlocking(false)這一步熟悉nio的小伙伴也不陌生, 就是將jdk的SocketChannel設置為非阻塞

我們繼續跟到父類構造方法中:

protected AbstractChannel(Channel parent) {
    this.parent = parent;
    id = newId();
    unsafe = newUnsafe();
    pipeline = newChannelPipeline();
}

這里初始化parent, 也就是創建自身的NioServerSocketChannel, 并為自身創建了唯一id

初始化unsafe, 我們跟到newUnsafe()方法中

由于此方法是NioEventLoop調用的, 所以會走到其父類AbstractNioByteChannel的newUnsafe()

跟到newUnsafe()中:

protected AbstractNioUnsafe newUnsafe() {
    return new NioByteUnsafe();
}

這里創建了NioByteUnsafe對象, 所以NioSocketChannel對應的unsafe是NioByteUnsafe

繼續往下跟, 我們看到其初始化了pipeline, 有關pipline的知識, 我們會在下一章節中講到

回到NioSocketChannel中的構造方法:

public NioSocketChannel(Channel parent, SocketChannel socket) {
    super(parent, socket);
    config = new NioSocketChannelConfig(this, socket.socket());
}

同NioServerSocketChannel一樣, 這里也初始化了一個Config屬性, 傳入兩個參數, 當前NioSocketChannel自身和jdk的底層SocketChannel的socket對象

我們跟進其構造方法

private NioSocketChannelConfig(NioSocketChannel channel, Socket javaSocket) {
    super(channel, javaSocket);
}

同樣, 這個類是NioSocketChannel的內部類

繼續跟父類構造方法:

public DefaultSocketChannelConfig(SocketChannel channel, Socket javaSocket) {
    super(channel);
    if (javaSocket == null) {
        throw new NullPointerException("javaSocket");
    }
    //保存當前javaSocket
    this.javaSocket = javaSocket;
    //是否禁止Nagle算法
    if (PlatformDependent.canEnableTcpNoDelayByDefault()) {
        try {
            setTcpNoDelay(true);
        } catch (Exception e) {
        }
    }
}

這里保存了SocketChannel的socket對象, 并且默認的情況禁止了Nagle算法, 有關Nagle, 感興趣的同學可以學習下相關知識

繼續跟到父類構造方法中:

public DefaultChannelConfig(Channel channel) {
    this(channel, new AdaptiveRecvByteBufAllocator());
}

又跟到到了我們熟悉的部分了, 也就是說, 無論NioServerSocketChannel和NioSocketChannel, 最后都會初始化DefaultChannelConfig, 并創建可變ByteBuf分配器, 我們之前小節對此做過詳細剖析這里不再贅述。

以上是“Netty客戶端接入流程NioSocketChannel怎么創建”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

城步| 桓仁| 宁化县| 司法| 石台县| 垦利县| 拜泉县| 任丘市| 定结县| 招远市| 通道| 如东县| 西昌市| 安平县| 南澳县| 达尔| 社会| 长宁区| 万年县| 合江县| 屏东县| 托里县| 磴口县| 海盐县| 库伦旗| 扶风县| 峨眉山市| 常宁市| 乡城县| 沐川县| 嘉祥县| 江都市| 台中县| 贞丰县| 曲周县| 德昌县| 舒兰市| 固安县| 新干县| 个旧市| 右玉县|