版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hxcaifly/article/details/85275544
承接上文:https://blog.csdn.net/hxcaifly/article/details/85274664
前言
单纯地使用Java JDK来实现网络NIO是一件开发成本非常高的事情。然而,Netty 为它所有的传输实现提供了一个通用API,这使得这种转换比你直接使用JDK所能够达到的简单得多。所产生的代码不会被实现的细节所污染,而你也不需要在你的整个代码库上进行广泛的重构。简而言之,你可以将时间花在其他更有成效的事情上。
1. Netty实现OIO
Netty实现OIO代码:
package chx.net.demo;
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;
public class NettyOioServer {
public void server(int port)
throws Exception {
final ByteBuf buf =
Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Hi!\r\n", Charset.forName("UTF-8")));
EventLoopGroup group = new OioEventLoopGroup();
try {
// 1.创建 ServerBootstrap
ServerBootstrap b = new ServerBootstrap();
b.group(group)
// 2.使用 OioEventLoopGroup以允许阻塞模式(旧的I/O)
.channel(OioServerSocketChannel.class)
.localAddress(new InetSocketAddress(port))
// 3.指定 ChannelInitializer,对于每个已接受的连接都调用它
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch)
throws Exception {
ch.pipeline().addLast(
// 4.添加一个 ChannelInboundHandlerAdapter以拦截和处理事件
new ChannelInboundHandlerAdapter() {
@Override
public void channelActive(
ChannelHandlerContext ctx)
throws Exception {
ctx.writeAndFlush(buf.duplicate())
.addListener(
//5.将消息写到客户端,并添加 ChannelFutureListener,以便消息一被写完就关闭连接
ChannelFutureListener.CLOSE);
}
});
}
});
// 6.绑定服务器以接受连接
ChannelFuture f = b.bind().sync();
f.channel().closeFuture().sync();
} finally {
// 7.释放所有的资源
group.shutdownGracefully().sync();
}
}
}
接下来,我们使用Netty 和非阻塞I/O 来实现同样的逻辑。
2. 非阻塞的Netty 版本
package chx.net.demo;
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;
public class NettyNioServer {
public void server(int port) throws Exception {
final ByteBuf buf =
Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Hi!\r\n",
Charset.forName("UTF-8")));
// 1.为非阻塞模式使用NioEventLoopGroup
NioEventLoopGroup group = new NioEventLoopGroup();
try {
// 2.创建ServerBootstrap
ServerBootstrap b = new ServerBootstrap();
b.group(group).channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(port))
// 3.指定 ChannelInitializer,对于每个已接受的连接都调用它
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch)
throws Exception {
ch.pipeline().addLast(
// 3.添加 ChannelInboundHandlerAdapter以接收和处理事件
new ChannelInboundHandlerAdapter() {
@Override
public void channelActive(
// 4.将消息写到客户端,并添加ChannelFutureListener,
// 5.以便消息一被写完就关闭连接
ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(buf.duplicate())
.addListener(
ChannelFutureListener.CLOSE);
}
});
}
}
);
// 6.绑定服务器以接受连接
ChannelFuture f = b.bind().sync();
f.channel().closeFuture().sync();
} finally {
// 7.释放所有的资源
group.shutdownGracefully().sync();
}
}
}
可以看出,Netty实现OIO和NIO的代码很类似,主要是EventLoopGroup不同。Netty自己内部做的逻辑封装减去了我们很大的开发成本。