版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/uk8692/article/details/79602020
最近开始学习Netty,
服务端:
public class TimeServer {
public void bind(int port) throws Exception {
/**
* NioEventLoopGroup 是用来处理I/O操作的多线程事件循环器,
* Netty提供了许多不同的EventLoopGroup的实现用来处理不同传输协议,
* 在这个例子中我们实现了一个服务端的应用,因此会有2个NioEventLoopGroup会被使用。
* 第一个经常被叫做‘boss’,用来接收进来的连接。
* 第二个经常被叫做‘worker’,用来处理已经被接收的连接。
*/
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap server = new ServerBootstrap();
server.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
.childHandler(new ChildChannelHandler());
//绑定端口,同步等待成功
ChannelFuture future = server.bind(port).sync();
//等待服务端监听端口关闭
future.channel().closeFuture().sync();
} finally {
//优雅退出,释放线程池资源
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
private class ChildChannelHandler extends ChannelInitializer<SocketChannel>{
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new TimeServerHandler());
}
}
public static void main(String[] args) throws Exception {
int port = 8888;
new TimeServer().bind(port);
}
}
public class TimeServerHandler extends ChannelHandlerAdapter{
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
/*ByteBuf byteBuf = (ByteBuf) msg;
String message = new String(byteBuf.array());*/
ByteBuf byteBuf = (ByteBuf) msg;
byte[] buf = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(buf);
String message = new String(buf,"UTF-8");
System.out.println("the server received msg:"+message);
String resText = "你好,我已经收到你的消息!"+new Date(System.currentTimeMillis()).toString();
ByteBuf writeByteBuf = Unpooled.copiedBuffer(resText.getBytes());
ctx.write(writeByteBuf);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println(cause.getMessage());
ctx.close();
}
}
客户端:
public class TimeClinet {
public void connect(String host, int port) throws Exception {
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
Bootstrap server = new Bootstrap();
server.group(workerGroup)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new TimeClientHandler());
}
});
// 发起异步连接操作
ChannelFuture future = server.connect(host, port).sync();
// 等待客户端链路关闭
future.channel().closeFuture().sync();
} finally {
//优雅退出,释放NIO线程组
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
int port = 8888;
new TimeClinet().connect("127.0.0.1", port);
}
}
public class TimeClientHandler extends ChannelHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
String msg = "你好!TimeServer。。。。。。。。。";
ByteBuf byteBuf = Unpooled.copiedBuffer(msg.getBytes());
ctx.writeAndFlush(byteBuf);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf) msg;
byte[] buf = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(buf);
String message = new String(buf);
System.out.println("Now is :" + message);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
}
在这里,最初写这个代码的时候遇到了一点问题,那就是在服务端接收消息时,我的代码如下:
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf) msg;
String message = new String(byteBuf.array());
System.out.println("the server received msg:"+message);
}
在调试的时候发现报错:
查看Netty底层源码,发现UnpooledUnsafeDirectByteBuf并不支持array()方法。
原来为了提升性能,Netty默认的I/O Buffer使用直接内存DirectByteBuf,可以减少Socket读写的内存拷贝,即著名的 ”零拷贝”。
由于是直接内存,因此无法直接转换成堆内存,因此它并不支持array()方法。用户需要自己做内存拷贝。