Spring Boot 從Socket 到Netty網絡編程(下):Netty基本開發與改進【心跳、粘包與拆包、閑置連接】

上一篇:《Spring Boot 從Socket 到Netty網絡編程(上):SOCKET 基本開發(BIO)與改進(NIO)》

前言

????????前文中我們簡單介紹了基于Socket的BIO(阻塞式)與NIO(非阻塞式)網絡編程,無疑NIO在網絡傳輸中具備更先進;但是采用Socket的NIO需要大量的優化,對于開發人員來說我們要站在巨人的肩膀上開發,所以Netty才是真愛。

? ? ? ? TCP/IP? -> Socket ->Netty 是這樣一個關系,? ? ? ? Netty是基于Socket,Socket是基于TCP/IP。

基本開發

Netty

個人總結:基于NIO,提供簡潔的API,開發者專注于業務邏輯實現,而非關注于實現實現細節。

maven

<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.94.Final</version>
</dependency>

服務端 ServerBootstrap

服務

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;public class NettyServer {public static void main(String[] args) throws Exception {// 創建一個線程組,用于接收客戶端的連接EventLoopGroup bossGroup = new NioEventLoopGroup();// 創建數據處理線程組,用于處理已經連接的客戶端的數據讀寫操作EventLoopGroup workerGroup = new NioEventLoopGroup();try {//創建服務端的啟動對象,設置參數ServerBootstrap bootstrap = new ServerBootstrap();//設置兩個線程組boosGroup和workerGroupbootstrap.group(bossGroup, workerGroup)//設置服務端通道實現類型.channel(NioServerSocketChannel.class)//設置線程隊列得到連接個數.option(ChannelOption.SO_BACKLOG, 128)//設置保持活動連接狀態.childOption(ChannelOption.SO_KEEPALIVE, true)//使用匿名內部類的形式初始化通道對象.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {//給pipeline管道設置處理器socketChannel.pipeline().addLast(new NettyServerHandler());//服務端處理器}});//給workerGroup的EventLoop對應的管道設置處理器System.out.println("服務已啟動...");//綁定端口號,啟動服務端ChannelFuture channelFuture = bootstrap.bind(6666).sync();//對關閉通道進行監聽channelFuture.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}

方法類


import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;public class NettyClient {public static void main(String[] args) throws Exception {NioEventLoopGroup eventExecutors = new NioEventLoopGroup();try {//創建bootstrap對象,配置參數Bootstrap bootstrap = new Bootstrap();//設置線程組bootstrap.group(eventExecutors)//設置客戶端的通道實現類型.channel(NioSocketChannel.class)//使用匿名內部類初始化通道.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {//添加客戶端通道的處理器ch.pipeline().addLast(new NettyClientHandler());//給pipeline管道設置處理器}});System.out.println("客戶端準備就緒");//連接服務端ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6666).sync();//對通道關閉進行監聽channelFuture.channel().closeFuture().sync();} finally {//關閉線程組eventExecutors.shutdownGracefully();}}}

客戶端 Bootstrap

客戶端

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;public class NettyClient {public static void main(String[] args) throws Exception {NioEventLoopGroup eventExecutors = new NioEventLoopGroup();try {//創建bootstrap對象,配置參數Bootstrap bootstrap = new Bootstrap();//設置線程組bootstrap.group(eventExecutors)//設置客戶端的通道實現類型.channel(NioSocketChannel.class)//使用匿名內部類初始化通道.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {//添加客戶端通道的處理器ch.pipeline().addLast(new NettyClientHandler());//給pipeline管道設置處理器}});System.out.println("客戶端準備就緒");//連接服務端ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6666).sync();//對通道關閉進行監聽channelFuture.channel().closeFuture().sync();} finally {//關閉線程組eventExecutors.shutdownGracefully();}}}

方法類

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;import java.io.BufferedReader;
import java.io.InputStreamReader;public class NettyClientHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {String userInput;System.out.println("請輸入消息(輸入 exit 斷開連接):");BufferedReader console = new BufferedReader(new InputStreamReader(System.in));while ((userInput = console.readLine()) != null) {ctx.writeAndFlush(Unpooled.copiedBuffer(userInput , CharsetUtil.UTF_8));if ("exit".equalsIgnoreCase(userInput)) {System.out.println("連接已關閉。");break;}}}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {//接收服務端發送過來的消息ByteBuf byteBuf = (ByteBuf) msg;System.out.println("收到服務端" + ctx.channel().remoteAddress() + "的消息:" + byteBuf.toString(CharsetUtil.UTF_8));}
}

效果

優化加強

心跳機制

????????為了解決主從之間的服務的斷開與連接情況是否更深,所以需要用心跳做連接試驗從而在業務上做斷開重連等業務需求實現。

原理設計

  • IdleStateHandler 配置心跳
  • 繼承類處理心跳事件:userEventTriggered
  • Pipeline中處理

?服務

方法

客戶

方法

效果

處理粘包與拆包

????????由于網絡原因可能會出來數據切割不完整的情況,為了在拆解數據時能得到完整的數據需要用一定的約束使得雙方統一成一個固定標準。

原理設計

  • 配置類型:一般使用動態長度 LengthFieldBasedFrameDecoder
  • 自定義加碼與解碼
  • 配置到 pipeline中去

代碼

服務端

客戶端

加碼

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;import java.util.List;public class NetyyDecoder extends ByteToMessageDecoder {@Overrideprotected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {if (byteBuf.readableBytes() < 4){return;}byteBuf.markReaderIndex();int dataLength = byteBuf.readInt();byte[] data = new byte[dataLength];byteBuf.readBytes(data);list.add(new String(data, "UTF-8"));}
}

解碼

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;import java.nio.charset.StandardCharsets;public class NetyyEncoder extends MessageToByteEncoder<String> {@Overrideprotected void encode(ChannelHandlerContext channelHandlerContext, String s, ByteBuf byteBuf) throws Exception {byte[] bytes = s.getBytes(StandardCharsets.UTF_8);int length = bytes.length;byteBuf.writeInt(length);byteBuf.writeBytes(bytes);}
}

后記

以上代碼環境是JDK17、Spring Boot 3.X+ ,對Netty這個框架做了一些基本的介紹,當然憑這短短的一篇文章不可能做到詳盡,僅供初學都參考。整理不易,如有幫助請收藏,轉發請注明出處,關注博主不斷更新更多技術文章。

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

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

相關文章

python編寫賽博朋克風格天氣查詢程序

工具介紹 這個天氣查詢工具是一個基于 Python 的桌面應用程序,使用了tkinter庫來創建圖形用戶界面(GUI),并通過requests庫調用 Open - Meteo API 獲取天氣數據。它具有賽博朋克風格的界面設計,提供了當前天氣信息、15 天天氣預報以及詳細的天氣數據展示,同時還包含溫度趨…

從二叉樹到 STL:揭開 set 容器的本質與用法

前言&#xff1a; 上次介紹完二叉搜索樹后&#xff0c;更新中斷了一段時間&#xff0c;先向大家致歉。最近學習狀態有些起伏&#xff0c;但我正在努力調整&#xff0c;相信很快會恢復節奏。今天我們繼續深入探討——關聯容器&#xff0c;它在算法和工程中都非常常見和重要。 1…

uv管理spaCy語言模型

本文記錄如何在使用uv管理python項目dependencies時&#xff0c;把spaCy的模型也納入其中. spaCy 一、spaCy簡介 spaCy是一個開源的自然語言處理&#xff08;NLP&#xff09;庫&#xff0c;它主要用于處理文本數據。它支持多種語言&#xff0c;包括英語、中文等。它是由Expl…

python執行測試用例,allure報亂碼且未成功生成報告

allure執行測試用例時顯示亂碼&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;?&#xfffd;&#xfffd;&#xfffd;&#xfffd;?&#xfffd;&#xfffd;&#xfffd;??&#xfffd;&#xfffd;&#xfffd;?&#xfffd;&am…

Rust 學習筆記:Box<T>

Rust 學習筆記&#xff1a;Box Rust 學習筆記&#xff1a;Box<T\>Box\<T> 簡介使用 Box\<T\> 在堆上存儲數據啟用帶有 box 的遞歸類型關于 cons 列表的介紹計算非遞歸類型的大小使用 Box\<T\> 獲取大小已知的遞歸類型 Rust 學習筆記&#xff1a;Box<…

英語寫作中“不少于(小于)”no less than替代no fewer than的用法

no less than 1 liter of water&#xff0c;no fewer than 100 people 是我們的傳統用法。現代英語有一個有趣的現象&#xff0c;就是less 代替fewer 形容可數名詞&#xff0c;例如&#xff1a; Do you have 10 courses each week? No. We have less. 顯然按嚴格語法應該是…

競品分析六大步驟

一、引言 在產品打磨、市場推廣或戰略定位過程中&#xff0c;我們常常會面臨一個關鍵任務——競品分析。一份系統的競品分析不僅能幫助我們知己知彼&#xff0c;優化產品策略&#xff0c;更能成為決策層制定方向的重要依據。競品分析到底該怎么做&#xff1f;今天我將結合自己的…

【Java Web】9.Maven高級

&#x1f4d8;博客主頁&#xff1a;程序員葵安 &#x1faf6;感謝大家點贊&#x1f44d;&#x1f3fb;收藏?評論?&#x1f3fb; 文章目錄 一、分模塊設計與開發 1.1 介紹 1.2 實踐 二、繼承與聚合 2.1 繼承 繼承關系 版本鎖定 2.2 聚合 2.3 繼承與聚合對比 三、…

MySQL 全量、增量備份與恢復

一.MySQL 數據庫備份概述 備份的主要目的是災難恢復&#xff0c;備份還可以測試應用、回滾數據修改、查詢歷史數據、審計等。之前已經學習過如何安裝 MySQL&#xff0c;本小節將從生產運維的角度了解備份恢復的分類與方法。 1 數據備份的重要性 在企業中數據的價值至關…

第六個微信小程序:教師工具集

源于工作需要&#xff0c;下面開始。 安裝及使用 | Taro 文檔 vscode 代碼管理 git 輔助 開發技術如上&#xff1a; 1.開始創建模板 taro4.1.1 $ taro init teachers-tools 2.用vsocde開始吧。 選擇 第二個文件夾找一。 (base) PS D:\react\teachers-tools> pnpm…

Linux 里 su 和 sudo 命令這兩個有什么不一樣?

《小菜狗 Linux 操作系統快速入門筆記》目錄&#xff1a; 《小菜狗 Linux 操作系統快速入門筆記》&#xff08;01.0&#xff09;文章導航目錄【實時更新】 Linux 是一個多用戶的操作系統。在 Linux 中&#xff0c;理論上來說&#xff0c;我們可以創建無數個用戶&#xff0c;但…

Elastic 獲得 AWS 教育 ISV 合作伙伴資質,進一步增強教育解決方案產品組合

作者&#xff1a;來自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通過搜索 AI 和云創新推動教育領域的數字化轉型。 我們非常高興地宣布&#xff0c;Elastic 已獲得 AWS 教育 ISV 合作伙伴資質。這一重要認證表明&#xff0c;Elastic 作為 …

服務器被攻擊了怎么辦

可以上一個高防IP或者AI云防護都是可以的。&#xff08;有效防御CC、APl接口、http、tcp、WEB應用掃描/爬蟲、SYN、WAF、DDOS、UDP、入侵、滲透、SQL注入、XSS跨站腳本攻擊、遠程惡意代碼執行、session fixation、Webshell攻擊、惡意請求&#xff0c;惡意掃描、暴力破解、CSRF等…

【學習筆記】Circuit Tracing: Revealing Computational Graphs in Language Models

Circuit Tracing: Revealing Computational Graphs in Language Models 替代模型(Replacement Model)&#xff1a;用更多的可解釋的特征來替代transformer模型的神經元。 歸因圖(Attribution Graph)&#xff1a;展示特征之間的相互影響&#xff0c;能夠追蹤模型生成輸出時所采用…

靈活控制,modbus tcp轉ethernetip的 多功能水處理方案

油田自動化和先進的油氣行業軟件為油氣公司帶來了諸多益處。其中包括&#xff1a; 1.自動化可以消除多余的步驟、減少人為錯誤并降低運行設備所需的能量&#xff0c;從而降低成本。 2.油天然氣行業不斷追求高水平生產。自動化可以更輕松地減少計劃外停機時間&#xff0c;從而…

是否存在路徑(FIFOBB算法)

題目描述 一個具有 n 個頂點e條邊的無向圖&#xff0c;該圖頂點的編號依次為0到n-1且不存在頂點與自身相連的邊。請使用FIFOBB算法編寫程序&#xff0c;確定是否存在從頂點 source到頂點 destination的路徑。 輸入 第一行兩個整數&#xff0c;分別表示n 和 e 的值&#xff08;1…

windows VeraCrypt – 磁盤加密工具

下載鏈接&#xff1a;夸克網盤分享 VeraCrypt一款跨平臺(Windows/Mac/Linux)的磁盤加密工具&#xff0c;提供多層級數據保護方案&#xff1a;虛擬加密盤&#xff1a;在文件中創建可掛載的加密虛擬磁盤全設備加密&#xff1a;支持分區/USB/硬盤等存儲設備的全盤加密系統盤加密&…

客戶體驗數據使用的三種視角——場景視角

當企業收集到大量的客戶體驗數據之后&#xff0c;應該如何應用&#xff1f;有哪些主要的使用場景和分析視角&#xff1f;體驗家團隊通過三篇文章&#xff0c;陸續介紹三種體驗數據的使用場景&#xff0c;以幫助企業更有效地利用體驗數據進行改進。 01 宏觀層次的“旅程視角” …

時序數據庫IoTDB的UDF Sample算法在數據監控、故障預防的應用

一、數據監控在工業物聯網中的重要性 設備數據監控是工業物聯網&#xff08;IoT&#xff09;中最為廣泛應用的領域之一。通過實時監控工廠機械設備的運行狀態&#xff0c;企業能夠提前發現設備的潛在故障&#xff0c;從而實現預防性維護與可預測性維護。這一做法不僅能有效提升…

fastadmin fildList 動態下拉框默認選中

html頁面 <td><select class"form-control dtselect" data-rule"required" data-dtselected"<%row.type%>" name"<%name%>[<%index%>][type]">{foreach nametypeList idvo}<option value"{$vo…