当前位置: 首页 > news >正文

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方法当中,再这个方法进行初始化,记得传入你想监听的端口,如果你想监听多个端口,可以安这样的步骤之间重复再写一遍就行,因为是异步启动的。

相关文章:

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

1、先构建基本的netty框架 再下面的代码中我构建了一个最基本的netty实现websocket的框架&#xff0c;其他个性化部分再自行添加。 Slf4j public class TeacherServer {public void teacherStart(int port) throws InterruptedException {NioEventLoopGroup boss new NioEve…...

深入理解C语言指针:基础概念、语法和实际应用

导言&#xff1a; 在C语言编程中&#xff0c;指针是一个强大而灵活的概念&#xff0c;它直接涉及到内存的操作&#xff0c;为程序员提供了更多的控制权。本文将深入探讨C语言指针的基础概念、语法规则以及实际应用&#xff0c;帮助读者更好地理解和运用这一重要的编程工具。 1…...

百度云加速免费版下线,推荐几款目前仍旧免费的CDN

近日&#xff0c;百度云加速实施了新政策&#xff0c;将不再支持免费套餐服务。现在免费的CDN也越来越少了&#xff0c;推荐几款目前仍旧免费的CDN&#xff0c;大家且用且珍惜&#xff01; 1、雨云【点此直达】 源站为雨云产品可以免费使用CDN&#xff0c;源站非雨云产品流量包…...

HarmonyOS(五)—— 认识页面和自定义组件生命周期

前言 在前面我们通过如何创建自定义组件一文知道了如何如何自定义组件以及自定义组件的相关注意事项&#xff0c;接下来我们认识一下页面和自定义组件生命周期。 自定义组件和页面的关系 在开始之前&#xff0c;我们先明确自定义组件和页面的关系 自定义组件&#xff1a;Co…...

DevExpress WinForms TreeMap组件,用嵌套矩形可视化复杂分层数据

DevExpress WinForms TreeMap控件允许用户使用嵌套的矩形来可视化复杂的平面或分层数据结构。 DevExpress WinForms有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。同时能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风…...

IO口速度影响了什么?

我们在初学单片机的时候都知道单片机GPIO的作用是巨大的&#xff0c;在配置GPIO的时候&#xff0c;结构体初始化里有一个选项是配置输入输出速度的&#xff0c;对于这个速度输出是必须要配置的&#xff0c;输入没有明令说明需不需要配置。 这个速度对于学习过32单片机的都应该知…...

Verilog基础:时序调度中的竞争(一)

相关阅读 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 作为一个硬件描述语言&#xff0c;Verilog HDL常常需要使用语句描述并行执行的电路&#xff0c;但其实在仿真器的底层&#xff0c;这些并行执行的语句是有先后顺序…...

nginx 配置静态缓存全教程 (以及静态缓存文件没有生成)

一、第一步定义一个缓存目录设置目录结构 在 http 模块下定义(keys_zone 缓存区名&#xff1a;后面是缓存区大小 inactive 不活跃的文件多久清理 max_size 缓存区所占磁盘的上限 use_temp_path 默认关闭&#xff08;有需要自己百度&#xff09;) proxy_cache_path /path/your…...

自己动手打包构建编译cri-dockerd

1.背景 本机是 armv7l架构cpu&#xff0c;发现官方文档中竟然没有&#xff0c;因此需要自己编译下&#xff1b; [rootcontainer0 ~]# uname -a Linux container0 5.4.206-v7l.1.el7 #1 SMP Mon Jul 25 14:13:29 UTC 2022 armv7l armv7l armv7l GNU/Linux2.打包/构建/编译 gi…...

Self-Supervised Exploration via Disagreement论文笔记

通过分歧进行自我监督探索 0、问题 使用可微的ri直接去更新动作策略的参数的&#xff0c;那是不是就不需要去计算价值函数或者critic网络了&#xff1f; 1、Motivation 高效的探索是RL中长期存在的问题。以前的大多数方式要么陷入具有随机动力学的环境&#xff0c;要么效率…...

【网络奇幻之旅】那年我与区块链技术的邂逅

&#x1f33a;个人主页&#xff1a;Dawn黎明开始 &#x1f380;系列专栏&#xff1a;网络奇幻之旅 ⭐每日一句&#xff1a;追光的人&#xff0c;终会光芒万丈 &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4dd;收藏⭐️ 文章目录 &#…...

1.5.1 git/svn日志格式规范

文章目录 git日志规范一 基本原则二 日志格式1 type:2 keys3 subject4 body5 footergit日志规范 一 基本原则 《规则1》小步提交,每个功能模块分别提交 《规则2》源文件与修改文件,分别提交 《规则3》 二 日志格式 type:keys:subject:body:footer 1 type: - `feat`: 新…...

[autojs]ui线程中更新控件的值的问题

"ui"; ui.layout(<vertical><button id"autoFloatWindow" text"开启悬浮窗" textSize"15sp" /><button id"autoService" text"开启无障碍服务" textSize"15sp" /><button id"…...

机器视觉技术在现代汽车制造中的应用

原创 | 文 BFT机器人 机器视觉技术&#xff0c;利用计算机模拟人眼视觉功能&#xff0c;从图像中提取信息以用于检测、测量和控制&#xff0c;已广泛应用于现代工业&#xff0c;特别是汽车制造业。其主要应用包括视觉测量、视觉引导和视觉检测。 01 视觉测量 视觉测量技术用于…...

学习视频剪辑方法:AI智剪助力,批量处理短视频无忧

随着短视频的兴起&#xff0c;越来越多的人开始关注如何有效地制作和发布这些内容。但是&#xff0c;短视频的制作并不容易&#xff0c;要耗费大量的时间和精力。现在有很多AI智能剪辑工具可以快速、高效地制作短视频。其中&#xff0c;AI智剪是一款非常受欢迎的视频剪辑功能&a…...

振南技术干货集:制冷设备大型IoT监测项目研发纪实(3)

注解目录 1.制冷设备的监测迫在眉睫 1.1 冷食的利润贡献 1.2 冷设监测系统的困难 &#xff08;制冷设备对于便利店为何如何重要&#xff1f;了解一下你所不知道的便利店和新零售行业。关 于电力线载波通信的论战。&#xff09; 2、电路设计 2.1 防护电路 2.1.1 强电防护…...

1143. 最长公共子序列

给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删除某些字符&#xff08;也可以…...

EASYEXCEL(一)

1.读取excel 读监听器 Slf4j public class StudentReadListener extends AnalysisEventListener<Student> {// 每读一样&#xff0c;会调用该invoke方法一次Overridepublic void invoke(Student data, AnalysisContext context) {System.out.println("data "…...

竞赛YOLOv7 目标检测网络解读

文章目录 0 前言1 yolov7的整体结构2 关键点 - backbone关键点 - head3 训练4 使用效果5 最后 0 前言 世界变化太快&#xff0c;YOLOv6还没用熟YOLOv7就来了&#xff0c;如果有同学的毕设项目想用上最新的技术&#xff0c;不妨看看学长的这篇文章&#xff0c;学长带大家简单的…...

第一类曲线积分@对弧长的曲线积分

文章目录 abstract对弧长的曲线积分曲线形构件的质量第一类曲线积分曲线积分存在性利用曲线积分的定义描述曲线形构件质量问题推广曲线积分可加性闭曲线积分 曲线积分性质曲线积分的计算方法证明(部分推导) 小结曲线弧显函数形式方程下的曲线积分公式推广例例例 abstract 在积…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...