当前位置: 首页 > 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 在积…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

PostgreSQL——环境搭建

一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在&#xff0…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...