服务端
@Slf4j
@Component
public class NettyServer {
@Resource
private NettyProps nettyProperties;
@Resource
private ServerChannelInitializer serverChannelInitializer;
public void start() {
String port = nettyProperties.getPort();
ServerBootstrap bootstrap = new ServerBootstrap();
// 创建反应器线程组
NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
bootstrap.group(bossGroup, workerGroup)
// 2.设置服务器的通道实现,指定使用的channel
.channel(NioServerSocketChannel.class)
.localAddress(Integer.parseInt(port))
// 3.设置保持活动连接状态,接收队列,禁用nagle算法,保证低延迟
.option(ChannelOption.SO_BACKLOG, 1024)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.TCP_NODELAY, true);
// 4.给workerGroup 的 EventLoop 对应的管道设置处理器,绑定客户端连接时候触发操作
bootstrap.childHandler(serverChannelInitializer);
try {
// 5.启动服务器并绑定一个端口并且同步生成一个 ChannelFuture 对象
ChannelFuture channelFuture = bootstrap.bind().sync();
channelFuture.addListener((ChannelFutureListener) channelFuture1 -> {
if (channelFuture1.isSuccess()) {
log.info("采集服务启动成功,监听端口【{}】", port);
} else {
log.info("采集服务启动失败,监听端口【{}】,失败原因【{}】", port, channelFuture1.cause());
}
});
// 6.等待通道关闭的异步任务结束
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
log.error("===端口为:" + port + " 服务启动出现异常===");
} finally {
// 释放资源
log.error("===服务关闭===");
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
客户端
@Slf4j
@Component
public class NettyClient {
public void start() {
Bootstrap bootstrap = new Bootstrap();
NioEventLoopGroup group = new NioEventLoopGroup();
bootstrap.group(group).channel(NioSocketChannel.class);
bootstrap.handler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) {
ch.pipeline().addLast(new ClientEncoder());
}
});
try {
ChannelFuture future = bootstrap.connect("192.168.0.58", 7098).sync();
future.addListener((ChannelFutureListener) channelFuture1 -> {
if (channelFuture1.isSuccess()) {
log.info("添加客户端到缓存");
ClientCache.clients.put("client", future.channel());
} else {
log.info("客户端启动失败,失败原因", channelFuture1.cause());
}
});
future.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 释放资源
log.error("===服务关闭===");
group.shutdownGracefully();
}
}
}
启动
@Slf4j
@Component
public class ParseApplicationRunner implements ApplicationRunner {
@Resource
private NettyServer nettyServer;
@Resource
private NettyClient nettyClient;
@Override
public void run(ApplicationArguments args) {
// 启动客户端线程
Thread clientThread = new Thread(() -> {
nettyClient.start();
});
clientThread.start();
// 启动服务器线程
Thread serverThread = new Thread(() -> {
nettyServer.start();
});
serverThread.start();
}
}