1、结论代码写在最前面
/**
* 报警上报
*
* @author: xc
* @date: 2022-02-11 9:10
*/
@Component
@Slf4j
@RequiredArgsConstructor
public class NettyAlarmServer {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
private int port = 38081;
private final NettyAlarmWebSocketHandler nettyAlarmWebSocketHandler;
@PostConstruct
public void start() throws Exception {
log.info("netty报警上报服务端正在启动监听 ==> 端口号 ==> {}", port);
ServerBootstrap bootstrap = new ServerBootstrap()
.group(workerGroup, bossGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
.localAddress(this.port)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
// websocket协议本身是基于http协议的,所以这边也要使用http解编码器
socketChannel.pipeline().addLast(new HttpServerCodec());
// 以块的方式来写的处理器
socketChannel.pipeline().addLast(new ChunkedWriteHandler());
// netty是基于分段请求的,HttpObjectAggregator的作用是将请求分段再聚合,参数是聚合字节的最大长度
socketChannel.pipeline().addLast(new HttpObjectAggregator(1024 * 1024 * 1024));
// 最后一个参数设置为true 代表可以抓取到通配路径 上报的路径是 /alarm?sn=xxx&type=xxx
socketChannel.pipeline().addLast(
new WebSocketServerProtocolHandler(
"/alarm",
"WebSocket",
true,
65536 * 10,
false,
true)
);
// 自定义的处理器
socketChannel.pipeline().addLast(nettyAlarmWebSocketHandler);
}
});
// 服务器异步创建
ChannelFuture future = bootstrap.bind(port).sync();
// 关闭服务器通道 会 wait
future.channel().closeFuture();
}
@PreDestroy
public void destroy() throws InterruptedException {
// 释放线程池资源
workerGroup.shutdownGracefully().sync();
bossGroup.shutdownGracefully().sync();
}
}
追加这行配置即可实现ws地址栏后缀通配请求
// 最后一个参数设置为true 代表可以抓取到通配路径 上报的路径是 /alarm?sn=xxx&type=xxx
socketChannel.pipeline().addLast(
new WebSocketServerProtocolHandler(
"/alarm",
"WebSocket",
true,
65536 * 10,
false,
true)
);
2、原理分析(个人拙见)
netty对websocket的路径支持无法使用通配路径,如果强行开启客户端的路径uri参数但是服务端没有做去除这个限制,就会反映出客户端能连接,但是netty没有返回101状态码导致一会儿就断开连接并且无法接收到客户端的报文数据。宏观展示出来的效果就是,客户端连接一会就断开,无任何报错。
解决方法:
1、去除uri地址参数限制,放开一切,只检测前缀路径。
2、放开WebSocketServerProtocolHandler处理器的最后一个参数
3、自定义的处理器要放在最后,控制器放在上一个处理,防止客户端还是连接一下就掉线