Netty框架封装websocket协议进行地址栏后缀通配

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、自定义的处理器要放在最后,控制器放在上一个处理,防止客户端还是连接一下就掉线

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值