I've been wanting to look into standard NIO networking and walk away from Netty for awhile, I don't know why, I just feel like the knowledge would be great, however one thing that I do enjoy is being able to use an Input/Output "Stream". In NIO you can't directly use a stream from my understanding, which is why Netty uses the ChannelBuffer class, and the 14,000 other subclasses that come with it. I've managed to put the ChannelBuffer class into my NIO project, but I'm having a hard time figuring out where the data is added to the ChannelBuffer, and where the class that implements the ChannelBuffer is being initialized/passed off to the pipeline.
I've been digging for quite awhile, here's what I've found so far:
ServerBootstrap.java
Code:
@Override
public void channelOpen(
...
if (!"pipelineFactory".equals(e.getKey())) {
parentOptions.put(e.getKey(), e.getValue());
}
...
evt.getChannel().getConfig().setOptions(parentOptions);
ChannelConfig.java
Code:
/**
* Returns the default {@link ChannelBufferFactory} used to create a new
* {@link ChannelBuffer}. The default is {@link HeapChannelBufferFactory}.
* You can specify a different factory to change the default
* {@link ByteOrder} for example.
*/
ChannelBufferFactory getBufferFactory();
/**
* Sets the default {@link ChannelBufferFactory} used to create a new
* {@link ChannelBuffer}. The default is {@link HeapChannelBufferFactory}.
* You can specify a different factory to change the default
* {@link ByteOrder} for example.
*/
void setBufferFactory(ChannelBufferFactory bufferFactory);
DefaultChannelConfig.java
Code:
public boolean setOption(String key, Object value) {
if (key == null) {
throw new NullPointerException("key");
}
if ("pipelineFactory".equals(key)) {
setPipelineFactory((ChannelPipelineFactory) value);
} else if ("connectTimeoutMillis".equals(key)) {
setConnectTimeoutMillis(ConversionUtil.toInt(value));
} else if ("bufferFactory".equals(key)) {
setBufferFactory((ChannelBufferFactory) value);
} else {
return false;
}
return true;
}
DefaultNioServerSocketConfig.java
Code:
@Override
public void setOptions(Map<String, Object> options) {
super.setOptions(options);
if (getWriteBufferHighWaterMark() < getWriteBufferLowWaterMark()) {
// Recover the integrity of the configuration with a sensible value.
setWriteBufferLowWaterMark0(getWriteBufferHighWaterMark() >>> 1);
if (logger.isWarnEnabled()) {
// Notify the user about misconfiguration.
logger.warn(
"writeBufferLowWaterMark cannot be greater than " +
"writeBufferHighWaterMark; setting to the half of the " +
"writeBufferHighWaterMark.");
}
}
}
@Override
public boolean setOption(String key, Object value) {
if (super.setOption(key, value)) {
return true;
}
if ("writeBufferHighWaterMark".equals(key)) {
setWriteBufferHighWaterMark0(ConversionUtil.toInt(value));
} else if ("writeBufferLowWaterMark".equals(key)) {
setWriteBufferLowWaterMark0(ConversionUtil.toInt(value));
} else if ("writeSpinCount".equals(key)) {
setWriteSpinCount(ConversionUtil.toInt(value));
} else if ("receiveBufferSizePredictorFactory".equals(key)) {
setReceiveBufferSizePredictorFactory((ReceiveBufferSizePredictorFactory) value);
} else if ("receiveBufferSizePredictor".equals(key)) {
setReceiveBufferSizePredictor((ReceiveBufferSizePredictor) value);
} else {
return false;
}
return true;
}
NioWorker.java
Code:
@Override
protected boolean read(SelectionKey k) {
...
final ChannelBufferFactory bufferFactory = channel.getConfig().getBufferFactory();
...
You can see that it's passing the Key/Value by String/Object where the object is a class, but I can't find at all where these are even being constructed from.
I've been tearing through these, class after class, but I've yet to figure out the implementation, basically I'm trying to implement the Netty ChannelBuffer in my own NIO application, for simplicity purposes.