Netty开发入门
Posted 落叶飞翔的蜗牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Netty开发入门相关的知识,希望对你有一定的参考价值。
Netty编程之HelloWorld
通过Netty的HelloWorld与NIO的HelloWord进行对比
分析一下两这个开发的复杂度,来证明Netty的意义
创建ServerSocketChannel,配置为非阻塞
绑定监听,配置TCP参数
创建一个独立的IO线程,用户轮询多路复用器Selector
创建Selector,将ServerSocketChannel注册到Selector上,监听ACCEPT事件
启动IO线程,在循环体中执行Selector.select()方法
轮询到就绪的Channel,对其进行判断,如果是ACCEPT状态,说明是客户端接入,调用ServerSocketChannel.accept()接收新的客户端
设置新接入客户端的SocketChannel为非阻塞,设置TCP参数
将SocketChannel注册到Selector,监听READ操作
如果轮询事件是READ, 说明SocketChannel有新的数据包就绪,构造ByteBuffer对象,读取数据包
如果轮询到WRITE事件,说明还有数据没有发送完,需要继续发送
可以发现,用NIO编程非常复杂,使用Netty编程可以简化开发。
public class TimeServer {
public void bind(int port) {
//配置服务器端NIO线程组
//NioEventLoopGroup是个线程组,包含了一组NIO线程,处理网络事件,实际上就是Reactor线程组
try (EventLoopGroup bossLoopGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup()){
//netty用于启动NIO服务端的启动类,目的是降低NIO开发的复杂度
ServerBootstrap bootstrap = new ServerBootstrap();
//功能类似于NIO中的ServerSocketChannel
bootstrap.group(bossLoopGroup, workerGroup).channel(NioserverSocketChannel.class)
//配置NioServerSocketChannel的参数
.option(ChannelOption.SO_BACKLOG, 1024)
//绑定事件的处理类ChildChannelHandler
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new TimeServerHandler());
}
});
//绑定端口,同步等待绑定操作完成
ChannelFuture channelFuture = bootstrap.bind(port).sync();
//等待服务器监听端口关闭
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
int port = 8888;
new TimeServer().bind(port);
}
}
服务器端处理类ChildChannelHandler具体处理逻辑如下:
public class TimeServerHandler extends ChannelHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
//类似NIO中的ByteBuffer
ByteBuf buf = (ByteBuf) msg;
//获取缓冲区可读字节数
byte[] req = new byte[buf.readableBytes()];
//缓冲区中的字节复制到字节数组
buf.readBytes(req);
String body = new String(req);
System.out.println("收到输入:" + body);
ByteBuf response = Unpooled.copiedBuffer(("当前时间:" + new Date()).getBytes());
//并不是直接把消息发送到SocketChannel中,只是把消息发送到缓冲数组,通过flush方法将消息发到SocketChannel
ctx.write(response);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
//将消息发送队列中的消息写入SocketChannel中,发送到对方
//防止频繁的唤醒Selector进行消息发送
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
//发生异常关闭ChannelHandlerContext等资源
ctx.close();
}
}
public class TimeClient {
public void connect(int port, String host) {
try (EventLoopGroup eventLoopGroup = new NioEventLoopGroup()){
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new TimeClientHandler());
}
});
//异步链接操作
ChannelFuture channelFuture = bootstrap.connect(host, port).sync();
//等待客户端
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
int port = 8888;
new TimeClient().connect(port, "127.0.0.1");
}
}
客户端处理类TimeClientHandler具体处理逻辑如下:
public class TimeClientHandler extends ChannelHandlerAdapter {
private final ByteBuf firstMessage;
public TimeClientHandler() {
byte[] req = "hello world".getBytes();
firstMessage = Unpooled.buffer(req.length);
firstMessage.writeBytes(req);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(firstMessage);
}
/**
* 读取并打印消息
* @param ctx
* @param msg
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
byte[] resp = new byte[buf.readableBytes()];
buf.readBytes(resp);
String body = new String(resp);
System.out.println(body);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
}
以上是关于Netty开发入门的主要内容,如果未能解决你的问题,请参考以下文章