NOTE

2.65 2.创建NioSocketChannel

1. 要分析的代码 this是netty服务端的channel,ch是jdk nio客户端的channel,NioSocketChannel是netty客户端的channel 2. NioSocketChannel构造函数 2.1. 设置对OP READ感兴趣 - 父类AbstractNioByte

Java创建于 更新于 historical

这是历史学习笔记,可能存在过时或不完整的理解。

1. 要分析的代码

buf.add(new NioSocketChannel(this, ch));

this是netty服务端的channel,ch是jdk nio客户端的channel,NioSocketChannel是netty客户端的channel

2. NioSocketChannel构造函数

public NioSocketChannel(Channel parent, SocketChannel socket) {
	//父类构造函数AbstractNioByteChannel
    super(parent, socket);
    //创建一个配置类NioSocketChannelConfig
    config = new NioSocketChannelConfig(this, socket.socket());
}

2.1. 设置对OP_READ感兴趣

  • 父类AbstractNioByteChannel构造函数
protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) {
	//父类AbstractNioChannel构造方法
	//对OP_READ事件感兴趣
    super(parent, ch, SelectionKey.OP_READ);
}

2.1.1. 配置channel为非阻塞

  • AbstractNioChannel
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
	//父类AbstractChannel构造方法
    super(parent);
    this.ch = ch;
    this.readInterestOp = readInterestOp;
    try {
    	//配置为非阻塞模式
        ch.configureBlocking(false);
    } catch (IOException e) {
        try {
            ch.close();
        } catch (IOException e2) {
            if (logger.isWarnEnabled()) {
                logger.warn(
                        "Failed to close a partially initialized socket.", e2);
            }
        }

        throw new ChannelException("Failed to enter non-blocking mode.", e);
    }
}
2.1.1.1. 创建channelId、unsafe、pipeline
  • AbstractChannel
protected AbstractChannel(Channel parent) {
    this.parent = parent;
	//channelId
    id = newId();
    //操作jdk底层nio
    unsafe = newUnsafe();
    //这个客户端channel也有pipeline?
    pipeline = newChannelPipeline();
}

2.2. 创建一个配置类NioSocketChannelConfig

private NioSocketChannelConfig(NioSocketChannel channel, Socket javaSocket) {
	//父类DefaultSocketChannelConfig构造方法
    super(channel, javaSocket);
    calculateMaxBytesPerGatheringWrite();
}

2.2.1. 关闭tcp delay

  • 父类DefaultSocketChannelConfig
public DefaultSocketChannelConfig(SocketChannel channel, Socket javaSocket) {
    super(channel);
    if (javaSocket == null) {
        throw new NullPointerException("javaSocket");
    }
    this.javaSocket = javaSocket;

    // Enable TCP_NODELAY by default if possible.
    //private static final boolean CAN_ENABLE_TCP_NODELAY_BY_DEFAULT = !isAndroid();
    //默认不是Android平台,返回true
    if (PlatformDependent.canEnableTcpNoDelayByDefault()) {
        try {
        	//关掉TcpDelay
        	//javaSocket.setTcpNoDelay(tcpNoDelay);
            setTcpNoDelay(true);
        } catch (Exception e) {
            // Ignore.
        }
    }
}
  • javaSocket.setTcpNoDelay(tcpNoDelay);
/**
 * Enable/disable {@link SocketOptions#TCP_NODELAY TCP_NODELAY}
 * (disable/enable Nagle's algorithm).
 *
 * @param on {@code true} to enable TCP_NODELAY,
 * {@code false} to disable.
 *
 * @exception SocketException if there is an error
 * in the underlying protocol, such as a TCP error.
 *
 * @since   JDK1.1
 *
 * @see #getTcpNoDelay()
 */
public void setTcpNoDelay(boolean on) throws SocketException {
    if (isClosed())
        throw new SocketException("Socket is closed");
	//其实就是设置tcp options
    getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
}

这里主要做的是禁止nagle算法:即尽量把小数据包集合成大数据包发送