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.pswp.cn/news/167959.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/167959.shtml
英文地址,請注明出處:http://en.pswp.cn/news/167959.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Day40力扣打卡

打卡記錄 包子湊數&#xff08;裴蜀定理 DP&#xff09; 根據裴蜀定理&#xff0c;存在 c gcd(a, b) 使不定方程ax by c滿足條件&#xff0c;如果gcd(a, b) 1即a與b互素的情況下&#xff0c;就會 ax by 1&#xff0c;由于為1可以構造后面的無窮數字&#xff0c;故得到結…

Centos7 離線安裝 CDH7.1.7

1. 安裝CDH的準備工作&#xff08;所有節點都要執行&#xff09; 1.1 準備環境 角色 IP k8s-master 192.168.181.129 k8s-node1 192.168.181.130 k8s-node2 192.168.181.131 1.2 安裝JDK # https://www.oracle.com/java/technologies/downloads/#java11 wget rpm -ivh…

亞馬遜Listing怎么寫!親身經驗分享

亞馬遜運營的重要環節之一&#xff0c;listing的攥寫&#xff0c;可以決定了產品的搜索排名&#xff0c;用戶的點擊率和轉化率&#xff0c;那么如果你的產品排名或者轉化不理想的情況&#xff0c;可以考慮對listing進行優化&#xff0c;在關鍵詞過多和語句流程通順的情況下&…

js獲取時間日期

目錄 Date 對象 1. 獲取當前時間 2. 獲取特定日期時間 Date 對象的方法 1. 獲取各種日期時間組件 2. 獲取星期幾 3. 獲取時間戳 格式化日期時間 1. 使用 toLocaleString() 方法 2. 使用第三方庫 UNIX 時間戳 內部表示 時區 Date 對象 JavaScript中內置的 Date 對象…

數據挖掘之PCA-主成分分析

PCA的用處&#xff1a;找出反應數據中最大變差的投影&#xff08;就是拉的最開&#xff09;。 在減少需要分析的指標同時&#xff0c;盡量減少原指標包含信息的損失&#xff0c;以達到對所收集數據進行全面分析的目的 但是什么時候信息保留的最多呢&#xff1f;具體一點&#…

?飛凌嵌入式FCU2601網關,為工商業儲能EMS注入智慧的力量

一、火熱的儲能行業&#xff0c;尋求新的市場機會 最近一段時間以來&#xff0c;世界儲能大會、上海儲能展、能源電子產業發展大會等多個儲能相關論壇和展覽密集登場&#xff0c;即使“內卷”已成為了業內討論的熱詞&#xff0c;但尋求新的市場機會仍然是行業共識&#xff0c;…

常用Redis的鍵命令參考

一、DEL DEL key [key …] 刪除給定的一個或多個 key 。 不存在的 key 會被忽略。 #刪除單個鍵127.0.0.1:6379> set name zhangsan OK 127.0.0.1:6379> del name (integer) 1# 刪除一個不存在的 key&#xff0c; 失敗&#xff0c;沒有 key 被刪除127.0.0.1:6379> E…

Qt C++中調用python,并將軟件打包發布,python含第三方依賴

工作中遇到qt c調用我的python 代碼&#xff0c;并且想要一鍵打包&#xff0c;這里我根據參考的以及個人實踐的結果來簡單實現一下。 環境&#xff1a;windows系統&#xff0c;QT Creater 4.5&#xff0c; python 3.8&#xff08;anaconda虛擬環境&#xff09; 1. 簡單QT調用…

【 Kubernetes 風云錄 】- Istio 應用多版本流量控制

文章目錄 原理實現DeploymentVirtualServiceDestinationRule 約束部署 目的: 根據不同的引擎版本&#xff0c;可以把請求發送到指定的引擎上。可以實現版本降級。 原理 Istio通過VirtualService和DestinationRule兩個資源對象來實現流量管理&#xff0c;其中VirtualService用于…

LeetCode Hot100 98.驗證二叉搜索樹

題目&#xff1a; 給你一個二叉樹的根節點 root &#xff0c;判斷其是否是一個有效的二叉搜索樹。 有效 二叉搜索樹定義如下&#xff1a; 節點的左子樹只包含 小于 當前節點的數。節點的右子樹只包含 大于 當前節點的數。所有左子樹和右子樹自身必須也是二叉搜索樹。 方法一…

electron windows robotjs 安裝教程

Robotjs 安裝 前言第一步 : 安裝python第二步 : 安裝Visual Studio 2022第三步 : 安裝robotjs 前言 robotjs可以控制鼠標鍵盤&#xff0c;獲取屏幕內容&#xff0c;配合electron可做很多自動化操作。windows下配置環境有很多坑&#xff0c;很多文章都太舊了。試了很多次發現了…

ky10 server x86 auditd安裝(日志審計系統)

概述 Auditd工具可以幫助運維人員審計Linux&#xff0c;分析發生在系統中的發生的事情。Linux 內核有用日志記錄事件的能力&#xff0c;包括記錄系統調用和文件訪問。管理員可以檢查這些日志&#xff0c;確定是否存在安全漏洞&#xff08;如多次失敗的登錄嘗試&#xff0c;或者…

golang學習筆記——接口和繼承比較2

接口和繼承 現在有一個需要要求大學生和足球運動員掌握英語技能&#xff0c;請問怎么實現? 給運動員和學生結構體添加studyEnglish方法顯示是可以的&#xff0c;但是籃球動員和中學生也學習了英語&#xff0c;顯示不行。這時&#xff0c;我們可以直接給足球運動員和大學生添加…

跳轉應用市場詳情頁market

關于作者&#xff1a;CSDN內容合伙人、技術專家&#xff0c; 從零開始做日活千萬級APP。 專注于分享各領域原創系列文章 &#xff0c;擅長java后端、移動開發、商業變現、人工智能等&#xff0c;希望大家多多支持。 未經允許不得轉載 目錄 一、導讀二、概覽三、跳轉到各大廠商應…

播放器開發(四):多線程解復用與解碼模塊實現

學習課題&#xff1a;逐步構建開發播放器【QT5 FFmpeg6 SDL2】 前言 根據第一章內容&#xff0c;我們首先可以先把解復用和解碼模塊完成&#xff0c;其中需要使用到多線程以及隊列&#xff0c;還需要使用FFmpeg進行解復用和解碼動作的實現。 創建BaseQueue基類 BaseQueue.h…

亞馬遜兩步驗證有哪些驗證方法?

亞馬遜通常提供多種兩步驗證的方式&#xff0c;包括短信&#xff08;通過手機接收驗證碼&#xff09;和認證器應用程序&#xff08;如Google Authenticator、Authy等&#xff09;。選擇你偏好的方式。 短信驗證&#xff1a; 如果選擇短信驗證&#xff0c;需要將你的手機號碼關聯…

YOLOv8改進 | 2023 | LSKAttention大核注意力機制助力極限漲點

論文地址&#xff1a;官方論文地址 代碼地址&#xff1a;官方代碼地址 一、本文介紹 在這篇文章中&#xff0c;我們將講解如何將LSKAttention大核注意力機制應用于YOLOv8&#xff0c;以實現顯著的性能提升。首先&#xff0c;我們介紹LSKAttention機制的基本原理&#xff0c;…

loginctl - 控制 systemd 登錄管理器

loginctl loginctl用途loginctl安裝開啟loginctl服務session操作user操作管理用戶服務 loginctl - Control the systemd login manager Redhat/centos平臺使用loginctl管理登錄用戶與session loginctl用途 控制 systemd 登錄管理器管理當前登錄的用戶和session loginctl安裝…

Peter算法小課堂—高精度加法

指針與數組 看看以下代碼&#xff0c;請預測答案 #include <bits/stdc.h> using namespace std; int x[10]{0,1,2,3,4,5,6,7,8,9}; int main(){cout<<x<<endl;cout<<x3<<endl;cout<<*x<<endl;cout<<*(x7)<<endl;cout&…

定制手機套餐---python序列

if __name__ __main__:print("定制手機套餐")print("")#定義電話時長&#xff1a;字典callTimeOptions{1:0分鐘,2:50分鐘,3:100分鐘,4:300分鐘,5:不限量}keyinput("請輸入電話時長的選擇編號&#xff1a;")valuecallTimeOptions.get(key)if val…