NOTE
2.65 2.创建NioSocketChannel
1. 要分析的代码 this是netty服务端的channel,ch是jdk nio客户端的channel,NioSocketChannel是netty客户端的channel 2. NioSocketChannel构造函数 2.1. 设置对OP READ感兴趣 - 父类AbstractNioByte
这是历史学习笔记,可能存在过时或不完整的理解。
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算法:即尽量把小数据包集合成大数据包发送