一、 Netty網絡框架、WebSocket協議基礎
????????1.1 Netty網絡框架介紹
????????1.2?WebSocket簡介
????????1.3 WebSocket握手流程
二、為什么選擇Netty+WebSocket?
三、Netty+WebSocket與Spring WebSocket
????????3.1 架構層級對比
????????3.2 核心組件差異
????????3.3?協議支持深度
????????3.4?性能基準測試
????????3.5?開發效率對比
????????3.6?典型應用場景
????????3.7 集成生態對比?編輯
四、基于Netty+WebSocket構建高性能實時通信系統
????????4.1 技術選型
????????4.2?pom.xml核心依賴
????????4.3?Netty服務的啟動類(服務器)
????????4.4 WebSocket初始化器
????????4.5 心跳處理類
????????4.6?消息處理器
????????4.7 Vue2 WebSocket連接核心代碼
五、總結
一、 Netty網絡框架、WebSocket協議基礎
1.1 Netty網絡框架介紹
參考我的另一篇文章:【Netty框架全解析】:從基礎概念到高階實踐,從零玩轉高性能網絡框架!-CSDN博客
1.2?WebSocket簡介
WebSocket是一種在單個TCP連接上進行全雙工通信的協議,解決了HTTP協議的半雙工和輪詢效率低的問題。其核心特點:
全雙工:客戶端和服務端可同時發送數據。
持久連接:一次握手后保持長連接。
低延遲:無需頻繁建立連接。
1.3 WebSocket握手流程
客戶端發起HTTP請求:包含Upgrade:websocket頭。
服務端響應101狀態碼:表示協議切換成功。
數據幀傳輸:后續通信通過二進制幀(Frame)進行。
握手請求示例:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Version: 13
握手響應示例:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
二、為什么選擇Netty+WebSocket?
在實時通信(IM)場景中,低延遲、高并發、長連接是核心需求。Netty作為高性能網絡框架,結合WebSocket協議,能夠完美滿足這些要求:
全雙工通信:WebSocket支持服務端主動推送,告別HTTP輪詢
低延遲:Netty的Reactor線程模型+零拷貝技術,輕松支撐10萬級并發
協議靈活:可擴展支持自定義二進制協議
本文將帶你從零開始實現一個完整的IM系統,涵蓋消息收發、用戶在線狀態管理、心跳檢測等核心功能,并提供可運行的完整代碼。
三、Netty+WebSocket與Spring WebSocket
3.1 架構層級對比
3.2 核心組件差異
Netty核心模塊
// 典型Netty WebSocket配置
pipeline.addLast(new HttpServerCodec()); // HTTP編解碼
pipeline.addLast(new HttpObjectAggregator(65536)); // 聚合HTTP請求
pipeline.addLast(new WebSocketServerProtocolHandler("/ws")); // 協議升級
pipeline.addLast(new CustomFrameHandler()); // 自定義業務處理
Spring核心模塊
// 典型Spring配置
@Configuration
@EnableWebSocket
public class Config implements WebSocketConfigurer {void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(myHandler(), "/ws");}
}
3.3?協議支持深度
3.4?性能基準測試
3.5?開發效率對比
3.6?典型應用場景
Netty更適合:
游戲服務器(需要自定義二進制協議)
金融級交易系統(微秒級延遲要求)
IoT設備接入(海量長連接管理)
Spring WebSocket更適合:
企業級消息通知系統
實時協作應用(如在線文檔)
需要快速集成Spring Security的場景
3.7 集成生態對比
四、基于Netty+WebSocket構建高性能實時通信系統
4.1 技術選型
Java?8+、Netty?4.x、WebSocket協議、Maven
4.2?pom.xml核心依賴
<dependencies><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.86.Final</version></dependency>
</dependencies>
4.3?Netty服務的啟動類(服務器)
/*** ChatServer: Netty 服務的啟動類(服務器)*/
public class ChatServer {public static void main(String[] args) throws Exception {// 定義主從線程組// 定義主線程池,用于接受客戶端的連接,但是不做任何處理,比如老板會談業務,拉到業務就會交給下面的員工去做了EventLoopGroup bossGroup = new NioEventLoopGroup();// 定義從線程池,處理主線程池交過來的任務,公司業務員開展業務,完成老板交代的任務EventLoopGroup workerGroup = new NioEventLoopGroup();try {// 構建Netty服務器ServerBootstrap server = new ServerBootstrap(); // 服務的啟動類server.group(bossGroup, workerGroup) // 把主從線程池組放入到啟動類中.channel(NioServerSocketChannel.class) // 設置Nio的雙向通道.childHandler(new WSServerInitializer()); // 設置處理器,用于處理workerGroup// 啟動server,并且綁定端口號875,同時啟動方式為"同步"ChannelFuture channelFuture = server.bind(875).sync();// 請求:http://127.0.0.1:875// 監聽關閉的channelchannelFuture.channel().closeFuture().sync();} finally {// 優雅的關閉線程池組bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}}
4.4 WebSocket初始化器
/*** 初始化器,channel注冊后,會執行里面的相應的初始化方法*/
public class WSServerInitializer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel channel) throws Exception {// 通過SocketChannel獲得對應的管道ChannelPipeline pipeline = channel.pipeline();/*** 通過管道,添加handler處理器*/// HttpServerCodec 是由netty自己提供的助手類,此處可以理解為管道中的攔截器// 當請求到服務端,我們需要進行做解碼,相應到客戶端做編碼// websocket 基于http協議,所以需要有http的編解碼器pipeline.addLast(new HttpServerCodec());// 添加對大數據流的支持pipeline.addLast(new ChunkedWriteHandler());// 對httpMessage進行聚合,聚合成為FullHttpRequest或FullHttpResponse// 幾乎在netty的編程中,都會使用到此handlerpipeline.addLast(new HttpObjectAggregator(1024 * 64));// ==================== 以上是用于支持http協議相關的handler ====================// ==================== 增加心跳支持 start ====================// 針對客戶端,如果在5小時沒有向服務端發送讀寫心跳(ALL),則主動斷開連接// 如果是讀空閑或者寫空間,不做任何處理(參數分別對應讀空閑、寫空閑、讀寫空閑秒數)pipeline.addLast(new IdleStateHandler(8,10,300 * 60));pipeline.addLast(new HeartBeatHandler());// ==================== 增加心跳支持 end ====================// ==================== 以下是用于支持websocket ====================/*** WebSocket 服務器處理的協議,用于指定給客戶端連接的時候訪問路由: /ws* 此Handler會幫我們處理一些比較復雜的繁重的操作* 會處理一些握手操作:handShaking(close,ping,pong)ping + pong = 心跳* 對于WebSocket來說,數據都是以frames(幀)進行傳輸的,不同的數據類型所對應的frames(幀)也都不同*/pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));// 添加自定義的助手類pipeline.addLast(new ChatHandler());}
}
4.5 心跳處理類
/*** 創建心跳助手類*/
public class HeartBeatHandler extends ChannelInboundHandlerAdapter {@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {// 判斷evt是否是IdleStateEvent(空閑事件狀態,包含 讀空閑/寫空閑/讀寫空閑)if (evt instanceof IdleStateEvent) {IdleStateEvent event = (IdleStateEvent)evt;if (event.state() == IdleState.READER_IDLE) {// System.out.println("進入讀空閑...");} else if (event.state() == IdleState.WRITER_IDLE) {// System.out.println("進入寫空閑...");} else if (event.state() == IdleState.ALL_IDLE) {Channel channel = ctx.channel();// 關閉無用的channel,以防資源浪費channel.close();}}}
}
4.6?消息處理器
/*** 創建自定義助手類*/
// SimpleChannelInboundHandler: 對于請求來說,相當于入站(入境)
// TextWebSocketFrame: 用于為websocket專門處理的文本數據對象,Frame是數據(消息)的載體
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {// 存儲所有連接的Channelprivate static final ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);@Overridepublic void channelActive(ChannelHandlerContext ctx) {clients.add(ctx.channel());System.out.println("客戶端連接: " + ctx.channel().id());}@Overridepublic void channelInactive(ChannelHandlerContext ctx) {clients.remove(ctx.channel());System.out.println("客戶端斷開: " + ctx.channel().id());}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) {String msg = frame.text();System.out.println("收到消息: " + msg);// 方案1:廣播給所有客戶端clients.writeAndFlush(new TextWebSocketFrame("[廣播] " + msg));// 方案2:轉發給特定客戶端(示例邏輯)if (msg.startsWith("@")) {forwardToTargetClient(msg);}}private void forwardToTargetClient(String msg) {String targetId = msg.substring(1, msg.indexOf(" "));String content = msg.substring(msg.indexOf(" ") + 1);clients.stream().filter(ch -> ch.id().asShortText().equals(targetId)).findFirst().ifPresent(ch -> ch.writeAndFlush(new TextWebSocketFrame("[私信] " + content)));}/*** 發生異常并且捕獲,移除channel*/@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {clients.remove(ctx.channel());ctx.close();cause.printStackTrace();}
}
4.7 Vue2 WebSocket連接核心代碼
// src/utils/websocket.js
export default class SocketService {static instance = nullstatic get Instance() {if (!this.instance) {this.instance = new SocketService()}return this.instance}// 連接狀態標記connected = falsews = null// 初始化連接connect() {if (!this.connected) {this.ws = new WebSocket('ws://localhost:875')this.ws.onopen = () => {this.connected = trueconsole.log('Netty連接成功')}this.ws.onmessage = (msg) => {console.log('收到消息:', msg.data)// 這里可以觸發Vuex的action處理消息}this.ws.onclose = () => {this.connected = falseconsole.log('Netty連接關閉')}this.ws.onerror = (err) => {console.error('連接錯誤:', err)}}}// 發送消息send(data) {if (this.connected) {this.ws.send(JSON.stringify(data))} else {console.error('尚未建立連接')}}
}
<template><div><button @click="connect">連接Netty</button><button @click="sendTestMsg">發送測試消息</button><div v-for="(msg, index) in messages" :key="index">{{ msg }}</div></div>
</template><script>
import SocketService from '@/utils/websocket'export default {data() {return {messages: []}},methods: {connect() {SocketService.Instance.connect()},sendTestMsg() {SocketService.Instance.send({type: 'test',content: 'Hello Netty!',timestamp: Date.now()})}},mounted() {// 可選:組件加載時自動連接// this.connect()}
}
</script>
4.8 Spring WebSocket實現簡單通信系統
參考我的文章:【Spring WebSocket詳解】Spring WebSocket從入門到實戰-CSDN博客
五、總結
本文通過Netty框架實現了基于WebSocket協議的簡單通信系統,覆蓋了從基礎握手、消息處理到心跳檢測的全流程。實際開發中還需考慮安全性(如WSS加密)、跨域處理、消息持久化等高級功能。如果你對上文有什么其他理解或者問題歡迎評論區留言討論!