Netty实现websocket且实现url传参的两种方式(源码分析)

1、先构建基本的netty框架

再下面的代码中我构建了一个最基本的netty实现websocket的框架,其他个性化部分再自行添加。

@Slf4j
public class TeacherServer {public void teacherStart(int port) throws InterruptedException {NioEventLoopGroup boss = new NioEventLoopGroup();NioEventLoopGroup worker = new NioEventLoopGroup(2);try{ServerBootstrap serverBootstrap = new ServerBootstrap().group(boss, worker).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel nsc) throws Exception {//http的编解码器nsc.pipeline().addLast(new HttpServerCodec());//将多个快组成一个完整的http请求nsc.pipeline().addLast(new HttpObjectAggregator(65536));nsc.pipeline().addLast(new WebSocketServerProtocolHandler("/teacher", null, true, 65536 * 10,false,true));}});ChannelFuture cf = serverBootstrap.bind(port).sync();log.info("教师服务已开启");cf.channel().closeFuture().sync();} finally {boss.shutdownGracefully().sync(); // 释放线程池资源worker.shutdownGracefully().sync();}}//初始化public void init(int port){//异步启动new Thread(() -> {try {teacherStart(port);} catch (InterruptedException e) {e.printStackTrace();}}).start();}
}

要实现websocket并且实现url传参,我们需要关注WebSocketServerProtocolHandler处理的一个参数:checkStartsWith

这个参数我们需要把他设置成ture,为什么呢,让我们来看一下源码isWebSockerPath(),这方法是判断具体的url是否和我设置的路径相匹配:

可以看出如果checkStartWith设为false的话,则必须url和websocketPath相等,否则会返回false。如果设置为true的话则只需要websocketPath是具体的url的前缀就行。当最后返回false时,连接就无法建立。

我们看源码这是一个处理类WebSocketServerProtocolHandshakeHandler,这是WebSocketServerProtocolHandler这个处理类再创建的时候给加pipelien()里的的,放在其之前,专门用来处理握手的处理器。可以看到如果返回false,则不会接下来进行握手操作,而是直接将消息返回给下一个处理器。如果这样的话我们可以认为连接已经失败。

所以我们如果要通过url传参的话再构建WebSocketServerProtocolHandler对象时要将chaekStartWith设为true。

2、获取url中的传参

        2.1 再没建立连接前获取url

        因为websocket发起建立连接用的时http协议并携带升级协议的请求,后面服务端进行升级,将其升为websocket,那么我们可以再还未升级前,也就是再WebSocketServerProtocolHandler处理器前再新增一个处理器,读取第一次发起的http请求。再其中获取url,等获取到初始化完后将这个处理器从pipelien中移除

FullRequest是一个Java类,它表示一个完整的HTTP请求,包含请求方法、路径、头部和内容。它是Netty框架中的一个组件,用于处理网络通信。

public class TeacherContineHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext channelHandlerContext, Object msg) throws Exception {if (msg instanceof FullHttpRequest){FullHttpRequest request = (FullHttpRequest) msg;String uri = request.uri();/**再这里编写自己的操作*/// 在本channel上移除这个handler消息处理,即只处理一次,鉴权通过与否channelHandlerContext.pipeline().remove(TeacherContineHandler.class);}super.channelRead(channelHandlerContext, msg);}
}

ps:主要放置顺序: 

2.2 建立后通过自定义事件HandshakeComplete获取url 

其实netty已经为我们想好了,我也是看源码才发现的,再连接建立完成后WebSocketServerProtocolHandshakeHandler会响应一个事件,再这个事件里我们可以获取到我们想要的请求路径和请求头,我们通过这个方法不光可以再url上传参,还能通过请求头传参。

 其中我们通过一个 那个futre对象,就是握手方法返回的,该对象是一个异步的操作结果,可以在完成时触发回调函数。当其完成时我们通过这个对象判断是否成功握手。如果握手成功,那么就调用localHandshakePromise的trySuccess方法,表示握手成功,并调用ctx.fireUserEventTriggered方法,触发两个用户自定义的事件,分别是:

  • ServerHandshakeStateEvent.HANDSHAKE_COMPLETE,表示握手完成的状态事件。
  • HandshakeComplete,表示握手完成的具体信息,包括req.uri()、req.headers()和handshaker.selectedSubprotocol(),分别表示WebSocket的URI地址、HttpRequest的头信息和选择的子协议。

那我们就可以通过监听这个用户自定义事件来获取请求体了。具体做法就是我们需要实现userEventTriggered()方法这个方法就是用来再有用户自定义事件发生时被调用的,

具体实现如下:

public class TeacherWebSocketHandler extends ChannelInboundHandlerAdapter {@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete){WebSocketServerProtocolHandler.HandshakeComplete handshakeComplete = (WebSocketServerProtocolHandler.HandshakeComplete) evt;String s = handshakeComplete.requestUri();HttpHeaders entries = handshakeComplete.requestHeaders();/*** 实现自己的初始化操作*/}super.userEventTriggered(ctx, evt);}
}

3、项目启动

我们的启动代码就写在main方法当中,再这个方法进行初始化,记得传入你想监听的端口,如果你想监听多个端口,可以安这样的步骤之间重复再写一遍就行,因为是异步启动的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/215109.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Prometheus环境搭建和认识

Prometheus 环境搭建 1.prometheus 简介 Prometheus是基于go语言开发的一套开源的监控、报警和时间序列数据库的组合&#xff0c;是由SoundCloud公司开发的开源监控系统&#xff0c;Prometheus于2016年加入CNCF&#xff08;Cloud Native Computing Foundation,云原生计算基金…

前端 vue 面试题(二)

文章目录 如何让vue页面重新渲染组件间通信vue为什么要mutation、 action操作插槽、具名插槽、作用域插槽vue编译使用的是什么库&#xff1f;vue怎么实现treeshakingwebpack实现treeshaking为什么只有es module 能支持 tree shaking mixin 的作用mixin的底层原理nexTick原理vue…

set和map + multiset和multimap(使用+封装(RBTree))

set和map 前言一、使用1. set(1)、模板参数列表(2)、常见构造(3)、find和count(4)、insert和erase(5)、iterator(6)、lower_bound和upper_bound 2. multiset3. map(1)、模板参数列表(2)、构造(3)、modifiers和operations(4)、operator[] 4. multimap 二、封装RBTree迭代器原理R…

python——第十三天

uuid 是通用唯一识别码&#xff08;Universally Unique identifier&#xff09;的缩写 UUID是一个128比特的数值 uuid模块&#xff1a; 获取一个128位&#xff08;比特&#xff09;的永不重复的数字&#xff0c;当然我们使用的时候会转换为32个的字符串 impor uuud uui…

React + BraftEditor 实现富文本编辑

Braft Editor 是一个基于 React 和 Draft-js 开发的富文本编辑器&#xff0c;提供了丰富的基础功能&#xff0c;如基本文本格式化、列表、链接、图片上传、视频插入等&#xff0c;并且还支持扩展。 首先&#xff0c;确保你已经在项目中安装了 Braft Editor 和它的依赖项&#x…

免费时代结束:百度云加速取消所有免费套餐

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 在网站时代&#xff0c;凭借着“品牌”“SEO”“免费”的优势&#xff0c;百度云加速一跃成为国内最大的CDN服务商。但随着站长时代结束&#xff0c;和网站相关的产品越来越少&#xff0c;收费的名…

Langchain的Agents介绍

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

卷积神经网络(CNN)识别验证码

文章目录 一、前言二、前期工作1. 设置GPU&#xff08;如果使用的是CPU可以忽略这步&#xff09;2. 导入数据3. 查看数据4.标签数字化 二、构建一个tf.data.Dataset1.预处理函数2.加载数据3.配置数据 三、搭建网络模型四、编译五、训练六、模型评估七、保存和加载模型八、预测 …

产品经理必备技能:竞品分析!秒懂竞品分析,写竞品分析报告看这篇就够了!

在这个竞争激烈的时代&#xff0c;每一个想要成功的企业不可避免地要进行竞品分析。竞品分析就像是一把锐利的剑&#xff0c;可以帮助我们洞察市场&#xff0c;了解对手&#xff0c;找出自己的优势和弱点。 但这并不是一件容易的事情&#xff0c;需要我们投入大量的时间和精力…

Fiddler 无法抓包手机 https 报文的解决方案来啦!!

解决手机https无法抓包的问题 当你测试App的时候&#xff0c;想要通过Fiddler/Charles等工具抓包看下https请求的数据情况&#xff0c;发现大部分的App都提示网络异常/无数据等等信息 这时候怎么解决呢&#xff1f; 以软件测试面试提刷题APP为例&#xff1a; Fiddler上的显示…

YOLOv5 第Y6周 模型改进

&#x1f368; 本文为[&#x1f517;365天深度学习训练营学习记录博客 &#x1f366; 参考文章&#xff1a;365天深度学习训练营 &#x1f356; 原作者&#xff1a;[K同学啊] &#x1f680; 文章来源&#xff1a;[K同学的学习圈子](https://www.yuque.com/mingtian-fkmxf/zxwb4…

Python之Pygame游戏编程详解

一、介绍 1.1 定义 Pygame是一种流行的Python游戏开发库&#xff0c;它提供了许多功能&#xff0c;使开发人员可以轻松创建2D游戏。它具有良好的跨平台支持&#xff0c;可以在多个操作系统上运行&#xff0c;例如Windows&#xff0c;MacOS和Linux。在本文中&#xff0c;我们将…