[netty5: WebSocketProtocolHandler]-源碼分析

在閱讀這篇文章前,推薦先閱讀:[netty5: MessageToMessageCodec & MessageToMessageEncoder & MessageToMessageDecoder]-源碼分析

WebSocketProtocolHandler

WebSocketProtocolHandler 是 WebSocket 處理的基礎抽象類,負責管理 WebSocket 幀的解碼、關閉流程及通用協議邏輯。

abstract class WebSocketProtocolHandler extends MessageToMessageDecoder<WebSocketFrame> {private final boolean dropPongFrames;private final WebSocketCloseStatus closeStatus;private final long forceCloseTimeoutMillis;private Promise<Void> closeSent;WebSocketProtocolHandler() {this(true);}WebSocketProtocolHandler(boolean dropPongFrames) {this(dropPongFrames, null, 0L);}WebSocketProtocolHandler(boolean dropPongFrames, WebSocketCloseStatus closeStatus, long forceCloseTimeoutMillis) {this.dropPongFrames = dropPongFrames;this.closeStatus = closeStatus;this.forceCloseTimeoutMillis = forceCloseTimeoutMillis;}@Overrideprotected void decode(ChannelHandlerContext ctx, WebSocketFrame msg) throws Exception {throw new UnsupportedOperationException("WebSocketProtocolHandler use decodeAndClose().");}@Overrideprotected void decodeAndClose(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception {if (frame instanceof PingWebSocketFrame) {try (frame) {ctx.writeAndFlush(new PongWebSocketFrame(frame.binaryData().send()));}readIfNeeded(ctx);return;}if (frame instanceof PongWebSocketFrame && dropPongFrames) {frame.close();readIfNeeded(ctx);return;}ctx.fireChannelRead(frame);}private static void readIfNeeded(ChannelHandlerContext ctx) {if (!ctx.channel().getOption(ChannelOption.AUTO_READ)) {ctx.read();}}@Overridepublic Future<Void> close(final ChannelHandlerContext ctx) {if (closeStatus == null || !ctx.channel().isActive()) {return ctx.close();}final Future<Void> future = closeSent == null ?write(ctx, new CloseWebSocketFrame(ctx.bufferAllocator(), closeStatus)) : closeSent.asFuture();flush(ctx);applyCloseSentTimeout(ctx);Promise<Void> promise = ctx.newPromise();future.addListener(f -> ctx.close().cascadeTo(promise));return promise.asFuture();}@Overridepublic Future<Void> write(final ChannelHandlerContext ctx, Object msg) {if (closeSent != null) {Resource.dispose(msg);return ctx.newFailedFuture(new ClosedChannelException());}if (msg instanceof CloseWebSocketFrame) {Promise<Void> promise = ctx.newPromise();closeSent(promise);ctx.write(msg).cascadeTo(closeSent);return promise.asFuture();}return ctx.write(msg);}void closeSent(Promise<Void> promise) {closeSent = promise;}private void applyCloseSentTimeout(ChannelHandlerContext ctx) {if (closeSent.isDone() || forceCloseTimeoutMillis < 0) {return;}Future<?> timeoutTask = ctx.executor().schedule(() -> {if (!closeSent.isDone()) {closeSent.tryFailure(buildHandshakeException("send close frame timed out"));}}, forceCloseTimeoutMillis, TimeUnit.MILLISECONDS);closeSent.asFuture().addListener(future -> timeoutTask.cancel());}protected WebSocketHandshakeException buildHandshakeException(String message) {return new WebSocketHandshakeException(message);}@Overridepublic void channelExceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {ctx.fireChannelExceptionCaught(cause);ctx.close();}
}

WebSocketServerProtocolHandler

WebSocketServerProtocolHandler 負責在服務器端管理 WebSocket 握手、幀的解碼與關閉處理,并支持協議校驗與異常處理。

public class WebSocketServerProtocolHandler extends WebSocketProtocolHandler {private static final AttributeKey<WebSocketServerHandshaker> HANDSHAKER_ATTR_KEY = AttributeKey.valueOf(WebSocketServerHandshaker.class, "HANDSHAKER");private final WebSocketServerProtocolConfig serverConfig;public WebSocketServerProtocolHandler(WebSocketServerProtocolConfig serverConfig) {super(Objects.requireNonNull(serverConfig, "serverConfig").dropPongFrames(),serverConfig.sendCloseFrame(),serverConfig.forceCloseTimeoutMillis());this.serverConfig = serverConfig;}// `handlerAdded` 方法負責在 ChannelPipeline 中動態添加握手處理器和 UTF-8 校驗器,確保 WebSocket 握手和數據幀合法性校驗功能生效。@Overridepublic void handlerAdded(ChannelHandlerContext ctx) {ChannelPipeline cp = ctx.pipeline();if (cp.get(WebSocketServerProtocolHandshakeHandler.class) == null) {// Add the WebSocketHandshakeHandler before this one.cp.addBefore(ctx.name(), WebSocketServerProtocolHandshakeHandler.class.getName(),new WebSocketServerProtocolHandshakeHandler(serverConfig));}if (serverConfig.decoderConfig().withUTF8Validator() && cp.get(Utf8FrameValidator.class) == null) {// Add the UFT8 checking before this one.cp.addBefore(ctx.name(), Utf8FrameValidator.class.getName(),new Utf8FrameValidator(serverConfig.decoderConfig().closeOnProtocolViolation()));}}@Overrideprotected void decodeAndClose(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception {// 當收到關閉幀時,優先通過已綁定的 WebSocketServerHandshaker 進行優雅關閉,否則直接關閉連接;非關閉幀則繼續正常處理。if (serverConfig.handleCloseFrames() && frame instanceof CloseWebSocketFrame) {WebSocketServerHandshaker handshaker = getHandshaker(ctx.channel());if (handshaker != null) {Promise<Void> promise = ctx.newPromise();closeSent(promise);handshaker.close(ctx, (CloseWebSocketFrame) frame).cascadeTo(promise);} else {frame.close();ctx.writeAndFlush(ctx.bufferAllocator().allocate(0)).addListener(ctx, ChannelFutureListeners.CLOSE);}return;}super.decodeAndClose(ctx, frame);}@Overrideprotected WebSocketServerHandshakeException buildHandshakeException(String message) {return new WebSocketServerHandshakeException(message);}@Overridepublic void channelExceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {if (cause instanceof WebSocketHandshakeException) {final byte[] bytes = cause.getMessage().getBytes();FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.BAD_REQUEST,ctx.bufferAllocator().allocate(bytes.length).writeBytes(bytes));ctx.channel().writeAndFlush(response).addListener(ctx, ChannelFutureListeners.CLOSE);} else {ctx.fireChannelExceptionCaught(cause);ctx.close();}}static WebSocketServerHandshaker getHandshaker(Channel channel) {return channel.attr(HANDSHAKER_ATTR_KEY).get();}static void setHandshaker(Channel channel, WebSocketServerHandshaker handshaker) {channel.attr(HANDSHAKER_ATTR_KEY).set(handshaker);}
}

WebSocketClientProtocolHandler

WebSocketClientProtocolHandler 是 Netty 中用于處理 WebSocket 客戶端協議升級、幀處理與自動注入握手與 UTF-8 校驗器的核心 ChannelHandler。

public class WebSocketClientProtocolHandler extends WebSocketProtocolHandler {private final WebSocketClientHandshaker handshaker;private final WebSocketClientProtocolConfig clientConfig;public WebSocketClientHandshaker handshaker() {return handshaker;}public WebSocketClientProtocolHandler(WebSocketClientProtocolConfig clientConfig) {super(Objects.requireNonNull(clientConfig, "clientConfig").dropPongFrames(),clientConfig.sendCloseFrame(), clientConfig.forceCloseTimeoutMillis());this.handshaker = WebSocketClientHandshakerFactory.newHandshaker(clientConfig.webSocketUri(),clientConfig.version(),clientConfig.subprotocol(),clientConfig.allowExtensions(),clientConfig.customHeaders(),clientConfig.maxFramePayloadLength(),clientConfig.performMasking(),clientConfig.allowMaskMismatch(),clientConfig.forceCloseTimeoutMillis(),clientConfig.absoluteUpgradeUrl(),clientConfig.generateOriginHeader());this.clientConfig = clientConfig;}@Overrideprotected void decodeAndClose(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception {if (clientConfig.handleCloseFrames() && frame instanceof CloseWebSocketFrame) {Resource.dispose(frame);ctx.close();return;}super.decodeAndClose(ctx, frame);}@Overrideprotected WebSocketClientHandshakeException buildHandshakeException(String message) {return new WebSocketClientHandshakeException(message);}// `handlerAdded` 方法會在當前 Handler 加入 pipeline 時,// 自動向其前方插入握手處理器和(可選的)UTF-8 校驗器,以確保 WebSocket 客戶端協議的正確初始化與安全性。@Overridepublic void handlerAdded(ChannelHandlerContext ctx) {ChannelPipeline cp = ctx.pipeline();if (cp.get(WebSocketClientProtocolHandshakeHandler.class) == null) {// Add the WebSocketClientProtocolHandshakeHandler before this one.ctx.pipeline().addBefore(ctx.name(), WebSocketClientProtocolHandshakeHandler.class.getName(),new WebSocketClientProtocolHandshakeHandler(handshaker, clientConfig.handshakeTimeoutMillis()));}if (clientConfig.withUTF8Validator() && cp.get(Utf8FrameValidator.class) == null) {// Add the UFT8 checking before this one.ctx.pipeline().addBefore(ctx.name(), Utf8FrameValidator.class.getName(),new Utf8FrameValidator());}}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/87687.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/87687.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/87687.shtml

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

相關文章

[2025CVPR]一種新穎的視覺與記憶雙適配器(Visual and Memory Dual Adapter, VMDA)

引言 多模態目標跟蹤&#xff08;Multi-modal Object Tracking&#xff09;旨在通過結合RGB模態與其他輔助模態&#xff08;如熱紅外、深度、事件數據&#xff09;來增強可見光傳感器的感知能力&#xff0c;尤其在復雜場景下顯著提升跟蹤魯棒性。然而&#xff0c;現有方法在頻…

理想汽車6月交付36279輛 第二季度共交付111074輛

理想汽車-W(02015)發布公告&#xff0c;2025年6月&#xff0c;理想汽車交付新車36279輛&#xff0c;第二季度共交付111074輛。截至2025年6月30日&#xff0c;理想汽車歷史累計交付量為133.78萬輛。 在成立十周年之際&#xff0c;理想汽車已連續兩年成為人民幣20萬元以上中高端市…

MobileNets: 高效的卷積神經網絡用于移動視覺應用

摘要 我們提出了一類高效的模型&#xff0c;稱為MobileNets&#xff0c;專門用于移動和嵌入式視覺應用。MobileNets基于一種簡化的架構&#xff0c;利用深度可分離卷積構建輕量級的深度神經網絡。我們引入了兩個簡單的全局超參數&#xff0c;能夠有效地在延遲和準確性之間進行…

SDP服務發現協議:動態查詢設備能力的底層邏輯(面試深度解析)

SDP的底層邏輯揭示了物聯網設備交互的本質——先建立認知,再開展協作。 一、SDP 核心知識點高頻考點解析 1.1 SDP 的定位與作用 考點:SDP 在藍牙協議棧中的位置及核心功能 解析:SDP(Service Discovery Protocol,服務發現協議)位于藍牙協議棧的中間層,依賴 L2CAP 協議傳…

CppCon 2018 學習:GIT, CMAKE, CONAN

提到的&#xff1a; “THE MOST COMMON C TOOLSET” VERSION CONTROL SYSTEM BUILDING PACKAGE MANAGEMENT 這些是 C 項目開發中最核心的工具鏈組成部分。下面我將逐一解釋每部分的作用、常見工具&#xff0c;以及它們如何協同構建現代 C 項目。 1. VERSION CONTROL SYSTEM&am…

使用tensorflow的線性回歸的例子(五)

我們使用Iris數據&#xff0c;Sepal length為y值而Petal width為x值。import matplotlib.pyplot as pltimport numpy as npimport tensorflow as tffrom sklearn import datasetsfrom tensorflow.python.framework import opsops.reset_default_graph()# Load the data# iris.d…

虛幻基礎:動作——蒙太奇

能幫到你的話&#xff0c;就給個贊吧 &#x1f618; 文章目錄 動作——蒙太奇如果動作被打斷&#xff0c;則后續的動畫通知不會執行 動作——蒙太奇 如果動作被打斷&#xff0c;則后續的動畫通知不會執行

[工具系列] 開源的 API 調試工具 Postwoman

介紹 隨著 Web 應用的復雜性增加&#xff0c;API 測試已成為開發中不可或缺的一部分&#xff0c;無論是前端還是后端開發&#xff0c;確保 API 正常運行至關重要。 Postman 長期以來是開發者進行 API 測試的首選工具&#xff0c;但是很多基本功能都需要登陸才能使用&#xff…

【力扣 簡單 C】746. 使用最小花費爬樓梯

目錄 題目 解法一 題目 解法一 int min(int a, int b) {return a < b ? a : b; }int minCostClimbingStairs(int* cost, int costSize) {const int n costSize; // 樓頂&#xff0c;第n階// 爬到第n階的最小花費 // 爬到第n-1階的最小花費從第n-1階爬上第n階的花費…

python+django開發帶auth接口

pythondjango開發帶auth接口 # coding utf-8 import base64 from django.contrib import auth as django_authfrom django.core.exceptions import ObjectDoesNotExist from django.http import JsonResponsefrom sign.models import Eventdef user_auth(request):"&quo…

RBAC權限模型如何讓API訪問控制既安全又靈活?

url: /posts/9f01e838545ae8d34016c759ef461423/ title: RBAC權限模型如何讓API訪問控制既安全又靈活? date: 2025-07-01T04:52:07+08:00 lastmod: 2025-07-01T04:52:07+08:00 author: cmdragon summary: RBAC權限模型通過用戶、角色和權限的關聯實現訪問控制,核心組件包括用…

安達發|告別低效排產:APS高級排程如何助力電池企業智造升級?

在全球能源轉型的背景下&#xff0c;動力電池、儲能電池等市場需求快速增長&#xff0c;電池制造企業面臨著訂單波動大、工藝復雜、交期嚴格等挑戰。傳統的手工排產或基于ERP的簡單計劃模式已難以滿足高效、精準的生產需求。APS高級排程通過智能算法優化生產計劃&#xff0c;實…

數據結構20250620_數據結構考試

試卷01 天津金海通軟件筆試題 選擇題(4*416) 對于雙向循環鏈表,在p指針所指的結點之后插入s指針所指結點的操作應為 p->nexts; s->prip; p->next->pris; s->nextp->nextp->nexts; p->next->pris; s->prip; s->nextp->nexts->pri …

4. 尋找正序數組的中位數

題目&#xff1a; 給定兩個大小分別為 m 和 n 的正序&#xff08;從小到大&#xff09;數組 nums1 和 nums2。請你找出并返回這兩個正序數組的 中位數 。 算法的時間復雜度應該為 O(log (mn)) 。 示例&#xff1a; 輸入&#xff1a;nums1 [1,3], nums2 [2] 輸出&#xff1a…

DeepSeek飛機大戰小游戲HTML5(附源碼)

用DeepSeek幫忙生成的飛機大戰小游戲網頁版&#xff0c;基于HTML5。 提示詞prompt 幫我做一個網頁版的飛機大戰游戲 html5的游戲功能說明 玩家控制&#xff1a; 使用鍵盤方向鍵或WASD移動飛機 空格鍵發射子彈 移動設備支持觸摸控制 游戲機制&#xff1a; 敵機會從屏幕頂部隨機位…

全素山藥開發指南:從防癢處理到高可用食譜架構

摘要&#xff1a;本文系統性解析山藥的化學特性&#xff08;黏液蛋白/皂苷致癢機制&#xff09;及全素場景下的烹飪解決方案&#xff0c;提供6種高內聚低耦合的食譜實現&#xff0c;附完整防氧化與黏液控制技術方案。一、核心問題分析&#xff1a;山藥處理中的“痛點”致癢物質…

OpenLayers 入門指南:序言

本專欄旨在幫助零GIS基礎的開發人員系統掌握OpenLayers這一強大的開源Web地圖庫&#xff0c;通過 “理論實戰” 結合的方式&#xff0c;逐步實現從創建地圖到構建一個基礎地圖應用模版。無論你是前端開發者、GIS愛好者&#xff0c;都可以通過此專欄零基礎開始用OpenLayers開發一…

WebRTC輕量學習 libdatachannel

最近想了解一些在瀏覽器中推送音視頻流&#xff0c;尋找很多版本的代碼&#xff0c;C、Go、Python等語言實現的webRTC協議。 按照搭建難度和快速實現首選Python版本的WebRTC&#xff0c;這種是最適合原型開發的。 選型&#xff1a;C的開源庫libdatachannel Python的開源庫Ai…

Vue2中的keep-alive:組件狀態緩存與性能優化實戰指南

目錄 一、什么是keep-alive&#xff1f; 與普通組件切換的對比 二、核心用法詳解 1. 基礎用法&#xff1a;動態組件緩存 2. 路由視圖緩存 3. 生命周期鉤子 三、進階配置與優化 1. 精準控制緩存組件 &#xff08;1&#xff09;include/exclude屬性 &#xff08;2&…

FastAPI安全加固:密鑰輪換、限流策略與安全頭部如何實現三重防護?

url: /posts/f96ba438de34dc197fd2598f91ae133d/ title: FastAPI安全加固:密鑰輪換、限流策略與安全頭部如何實現三重防護? date: 2025-07-02T22:05:04+08:00 lastmod: 2025-07-02T22:05:04+08:00 author: cmdragon summary: FastAPI框架安全加固方案包括密鑰輪換自動化、請…