- 原理
检测字节数组中含有的“\n”或“\r\n”换行符,并一次作为字节数据包的结束位置;注意,若业务数据存在换行符,需要进行转义
- 案例
1.LineBaseServer:服务端
/**
* @author pdc
*/
public class LineBaseServer {
public static void main(String[] args) throws Exception {
int port = 8080;
new LineBaseServer().bind(port);
}
public void bind(int port) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
//创建服务端辅助启动类ServerBootstrap对象
ServerBootstrap b = new ServerBootstrap();
//设置NIO线程组
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
//设置TCP参数,连接请求的最大队列长度
.option(ChannelOption.SO_BACKLOG, 1024)
//设置I/O事件处理类,用来处理消息的编解码以及我们的业务逻辑
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
//设置LineBasedFrameDecoder处理器
ch.pipeline().addLast(new LineBasedFrameDecoder(1024));
//设置StringDecoder处理器
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new LineBaseServerHandler());
}
});
// 绑定端口,同步等待成功
ChannelFuture f = b.bind(port).sync();
// 等待服务端监听端口关闭
f.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 优雅退出释放线程池资源
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
2.LineBaseServerHandler:服务端业务处理器
/**
* @author pdc
*/
public class LineBaseServerHandler extends SimpleChannelInboundHandler {
//字符串分隔符
private static final String delimiter_tag = "@#";
//计数器
private static final AtomicInteger counter = new AtomicInteger(0);
@Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
//接收客户端发送的字符串,并打印到控制台
String content = (String) msg;
System.out.println("received from client:" + content + " counter:" + counter.addAndGet(1));
//将数据重新发送到客户端
content += "\n";
ByteBuf echo = Unpooled.copiedBuffer(content.getBytes());
ctx.writeAndFlush(echo);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
}
3.LineBaseClient:客户端
/**
* @author pdc
*/
public class LineBaseClient {
public static void main(String[] args) throws Exception {
int port = 8080;
new LineBaseClient().connect(port, "127.0.0.1");
}
public void connect(int port, String host) throws Exception {
//创建客户端处理I/O读写的NIO线程组
EventLoopGroup group = new NioEventLoopGroup();
try {
//创建客户端辅助启动类
Bootstrap b = new Bootstrap();
//设置NIO线程组
b.group(group)
//设置NioSocketChannel,对应与JDK NIO类SocketChannel类
.channel(NioSocketChannel.class)
//设置TCP参数TCP_NODELAY
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) throws Exception {
//设置LineBasedFrameDecoder处理器
ch.pipeline().addLast(new LineBasedFrameDecoder(1024));
//设置StringDecoder处理器
ch.pipeline().addLast(new StringDecoder());
//配置客户端处理网络I/O事件的类
ch.pipeline().addLast(new LineBaseClientHandler());
}
});
// 发起异步连接操作
ChannelFuture f = b.connect(host, port).sync();
//循环发送1000次
for (int i = 0; i < 1000; i++) {
//构造客户端发送的数据ByteBuf对象
String content = "你好,Netty!\n";
byte[] req = content.getBytes();
ByteBuf messageBuffer = Unpooled.buffer(req.length);
messageBuffer.writeBytes(req);
//向服务端发送数据
ChannelFuture channelFuture = f.channel().writeAndFlush(messageBuffer);
channelFuture.syncUninterruptibly();
}
// 等待客户端链路关闭
f.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 优雅退出,释放NIO线程组
group.shutdownGracefully();
}
}
}
4.LineBaseClientHandler:客户端业务处理器
/**
* @author pdc
*/
public class LineBaseClientHandler extends SimpleChannelInboundHandler {
private static final Logger logger = Logger.getLogger(LineBaseClientHandler.class.getName());
//计数器
private static final AtomicInteger counter = new AtomicInteger(0);
//服务端响应请求返回数据的时候会自动调用该方法,我们通过实现该方法来接收服务端返回的数据,并实现客户端调用的业务逻辑
@Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
//获取服务端返回的数据,并打印到控制台
String content = (String) msg;
System.out.println("received from server:" + content + " counter:" + counter.addAndGet(1));
}
//发生异常,关闭链路
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
logger.warning("Unexpected exception from downstream :" + cause.getMessage());
ctx.close();
}
}
- 运行
先运行LineBaseServer的main,再运行LineBaseClient的main即可