NOTE

2. Create NioSocketChannel

1. Code to analyze 2. NioSocketChannel constructor

JavaCreated Updated 1 min readhistorical

This is a historical learning note and may contain outdated or incomplete understanding.

1. Code to Analyze

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

this is Netty’s server-side channel, ch is the JDK NIO client channel, and NioSocketChannel is Netty’s client-side channel.

2. NioSocketChannel Constructor

public NioSocketChannel(Channel parent, SocketChannel socket) {
    // Parent constructor: AbstractNioByteChannel.
    super(parent, socket);
    // Create configuration class NioSocketChannelConfig.
    config = new NioSocketChannelConfig(this, socket.socket());
}

2.1. Set Interest in OP_READ

  • Parent constructor AbstractNioByteChannel
protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) {
    // Parent constructor AbstractNioChannel.
    // Interested in OP_READ events.
    super(parent, ch, SelectionKey.OP_READ);
}

2.1.1. Configure the Channel as Non-Blocking

  • AbstractNioChannel
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
    // Parent constructor AbstractChannel.
    super(parent);
    this.ch = ch;
    this.readInterestOp = readInterestOp;
    try {
        // Configure non-blocking mode.
        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. Create channelId, unsafe, and pipeline
  • AbstractChannel
protected AbstractChannel(Channel parent) {
    this.parent = parent;
    // channelId
    id = newId();
    // Operates on the underlying JDK NIO layer.
    unsafe = newUnsafe();
    // This client channel also has a pipeline.
    pipeline = newChannelPipeline();
}

2.2. Create NioSocketChannelConfig

private NioSocketChannelConfig(NioSocketChannel channel, Socket javaSocket) {
    // Parent constructor DefaultSocketChannelConfig.
    super(channel, javaSocket);
    calculateMaxBytesPerGatheringWrite();
}

2.2.1. Disable TCP Delay

  • Parent class 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();
    // Non-Android platforms return true by default.
    if (PlatformDependent.canEnableTcpNoDelayByDefault()) {
        try {
            // Disable TCP delay.
            //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");
    // This ultimately sets the TCP option.
    getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
}

The main operation here is disabling Nagle’s algorithm, which otherwise tries to combine small packets into larger packets before sending them.

Discussion

Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub