Netty NIO transport && OIO transport
OIO transport
The OIO transport is a compromise(妥协) in Netty. It builds on the known unified(统一) API but isn t asynchronous(异步) by nature because it uses the blocking java.net implementations under the hood. At first glance, this transport may not look useful to you, but it has its use cases.
Because the OIO transport uses the java.net classes internally(内部的), it also uses the same logic that you may already be familiar with if you previously written network applications. When using these classes, you usually have one thread that handles the acceptance of new sockets (server-side) and then creates a new thread for each accepted connection to serve the traffic over the socket. This is needed as every I/O operation on the socket may block at any time. If you share the same thread over more than one connection (socket), this could lead to a situation where blocking an operation could block all other sockets from doing their work. Knowing that operations may block, you may start to wonder how Netty uses it while still providing the same way of building APIs. Here Netty makes use of the SO_TIMEOUT that you can set on a socket. This timeout specifies the maximum number of milliseconds to wait for an I/O operation to complete. If the operation doesn t complete within the specified timeout, a SocketTimeoutException is thrown. Netty catches this SocketTimeoutException and moves on with its work. Then on the next EventLooprun, it tries again. Unfortunately, this is the only way to do this and still confirm the inner working of Netty. The problem with this approach(途径) is that firing the SocketTimeoutException isn t free, as it needs to fill the StrackTrace, and so on.
Netty OIO 编程模型
package nio2;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.oio.OioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.oio.OioServerSocketChannel;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
/**
* Start by writing a blocking version of the application,
* but this time use Netty as a network
* framework, as shown in the following listing.
* 这是netty的阻塞IO的写法,同时也是同步的
*/
public class NettyOioServer {
public void server(int port) throws Exception {
final ByteBuf buf = Unpooled.wrappedBuffer(
Unpooled.copiedBuffer("Hi!\r\n", Charset.forName("UTF-8")));
// Use OioEventLoopGroup Ito allow blocking mode (Old-IO)
EventLoopGroup group = new OioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(group)
.channel(OioServerSocketChannel.class)
.localAddress(new InetSocketAddress(port))
//Specify ChannelInitializer that will be called for each accepted connection
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
//Add ChannelHandler to intercept events and allow to react on them
new ChannelInboundHandlerAdapter() {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("--active--");
//Write message to client and add ChannelFutureListener to close connection once message written
ctx.write(buf.duplicate()).addListener(ChannelFutureListener.CLOSE);
}
});
}
});
/**
* Bind server to accept connections
*/
ChannelFuture f = b.bind().sync();
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
}
}
public static void main(String args[]) throws Exception {
int port = 9898;
NettyOioServer server = new NettyOioServer();
System.out.println("bind port " + port);
server.server(port);
}
}
NIO transport
selector-based
The NIO transport is currently the most used. It provides a full asynchronous implementation of all I/O operations by using the selector-based approach that s included in Java since Java 1.4 and the NIO subsystem.
The idea is that a user can register to get notified once a channel s state changes.
Selection operation bit-set
OP_ACCEPT
Get notified once a new connection is accepted and a channel is created.
OP_CONNECT
Get notified once a connection attempt finishes.
OP_READ
Get notified once data is ready to be read out of the channel.
OP_WRITE
Get notified once it s possible to write more data to the channel. Most of the time this is possible, but it may not be because the OS socket buffer is completely filled. This usually happens when you write faster then the remote peer can handle it.
Netty s NIO transport uses this model internally to receive and send data, but exposes its own API to the user, which completely hides the internal implementation. As mentioned previously, that helps to expose only one unified(统一的) API to the user, while hiding all of the internals(内部).
One feature that offers only the NIO transport at the moment is called zero-file-copy . This feature allows you to quickly and efficiently transfer content from your file system. The feature provides a way to transfer the bytes from the file system to the network stack without copying the bytes from the kernel space(内核态) to the user space(用户态).
Netty NIO 异步非阻塞编程模型
package nio2;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
/**
* Asynchronous networking with Netty
* For now, I'll note that you can use ChannelHandlerfor these tasks:
* Transforming data from one format to another.
* Notifying you of exceptions.
* Notifying you when a Channel becomes active or inactive.
* Notifying you once a channel is registered/deregistered from an EventLoop.
* Notifying you about user-specific events.
*/
public class NettyNioServer {
public void server(int port) throws Exception {
final ByteBuf buf = Unpooled.wrappedBuffer(
Unpooled.copiedBuffer("Hi!\r\n", Charset.forName("UTF-8")));
EventLoopGroup group = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(group)
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(port))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new ChannelInboundHandlerAdapter() {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("--active--");
//Write message to client and add ChannelFutureListener to close connection once message written
ctx.write(buf.duplicate()).addListener(ChannelFutureListener.CLOSE);
}
});
}
});
/**
* Bind server to accept connections
*/
ChannelFuture f = b.bind().sync();
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
}
}
public static void main(String args[]) throws Exception {
int port = 9898;
NettyOioServer server = new NettyOioServer();
System.out.println("bind port " + port);
server.server(port);
}
}
附:Netty提供的传输方式包括:
OIO
NIO
Local
Embedded
四种,以上只讲了两种。
写在后边
虽然通篇都是英文,但读起来感觉还是不错的,不常见的英文单词标注了中文。
通过最近一段时间的读英文文档,发现读起来不是很费劲了,至少感觉比读中文文档少了很多歧义。
自然有了google翻译的帮助,不会的单词都是小case,呵呵
=======END=======
来源:oschina
链接:https://my.oschina.net/u/1469576/blog/282227