<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
由於上述原因,在大多數場景下,不建議大家直接使用JDK的NIO類庫,除非你精通NIO程式設計或者有特殊的需求。在絕大多數的業務場景中,我們可以使用NIO框架Netty來進行NIO程式設計,它既可以作為使用者端也可以作為伺服器端,同時支援UDP和非同步檔案傳輸,功能非常強大。
Netty是業界最流行的NIO框架之一,它的健壯性、功能、效能、可客製化性和可延伸性在同類框架中都是首屈一指的,它已經得到成百上千的商用專案驗證,例如Hadoop的RPC框架Avro就使用了Netty作為底層通訊框架,其他還有業界主流的RPC框架,也使用Netty來構建高效能的非同步通訊能力。
優點總結:
首先引入Netty的jar包。
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.42.Final</version> </dependency>
NettyServer 類
public class NettyServer { /** * netty啟動埠號 */ private static int port = 8080; public static void main(String[] args) { /** * 使用者端建立兩個執行緒池組分別為 boss執行緒組和工作執行緒組 */ // 用於接受使用者端連線的請求 (並沒有處理請求) NioEventLoopGroup bossGroup = new NioEventLoopGroup(); // 用於處理使用者端連線的讀寫操作(處理請求操作) NioEventLoopGroup workGroup = new NioEventLoopGroup(); ServerBootstrap serverBootstrap = new ServerBootstrap(); //NioServerSocketChannel 標記當前是伺服器端 serverBootstrap.group(bossGroup, workGroup).channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { // 設定我們分割最大長度為1024 socketChannel.pipeline().addLast(new LineBasedFrameDecoder(1024)); // 獲取資料的結果為string型別 socketChannel.pipeline().addLast(new StringEncoder()); //處理每個handler(也就是每次使用者端請求) socketChannel.pipeline().addLast(new ServerHandler()); } }); try { //繫結埠號 ChannelFuture bind = serverBootstrap.bind(port); ChannelFuture sync = bind.sync(); System.out.println("伺服器端啟動成功:" + port); //等待監聽我們的請求 sync.channel().closeFuture().sync(); }catch (Exception e){ e.printStackTrace(); }finally { //優雅的關閉我們的執行緒池 bossGroup.shutdownGracefully(); workGroup.shutdownGracefully(); } } }
ServerHandler 類
public class ServerHandler extends SimpleChannelInboundHandler { /* * @Author kaico * @Date 9:56 2020/10/8 * @Description //TODO 獲取資料 * @Param [channelHandlerContext, o] * @return void **/ @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception { ByteBuf byteBuf = (ByteBuf) o; String request = byteBuf.toString(CharsetUtil.UTF_8); System.out.println("request:" + request); // 響應內容: channelHandlerContext.writeAndFlush(Unpooled.copiedBuffer("這裡是Netty伺服器端n", CharsetUtil.UTF_8)); } }
NettyClient 類
public class NettyClient { public static void main(String[] args) { //建立nioEventLoopGroup NioEventLoopGroup group = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group).channel(NioSocketChannel.class) .remoteAddress(new InetSocketAddress("127.0.0.1", 8080)) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { // 設定我們分割最大長度為1024 ch.pipeline().addLast(new LineBasedFrameDecoder(1024)); // 獲取資料的結果為string型別 ch.pipeline().addLast(new StringEncoder()); ch.pipeline().addLast(new ClientHandler()); } }); try { // 發起同步連線 ChannelFuture sync = bootstrap.connect().sync(); sync.channel().closeFuture().sync(); } catch (Exception e) { } finally { group.shutdownGracefully(); } } }
ClientHandler 類
public class ClientHandler extends SimpleChannelInboundHandler { /** * 活躍通道可以傳送訊息 * * @param ctx * @throws Exception */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { for (int i = 0; i < 10; i++) { // 傳送資料 ctx.writeAndFlush(Unpooled.copiedBuffer("你是什麼型別的伺服器端啊?n", CharsetUtil.UTF_8)); } //使用者端發十條訊息 } /** * 讀取訊息 * * @param ctx * @param msg * @throws Exception */ @Override protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf byteBuf = (ByteBuf) msg; System.out.println("resp:" + byteBuf.toString(CharsetUtil.UTF_8)); } }
原因:因為我們現在tcp協定預設是長連線形式實現通訊,傳送請求完了之後整個連線暫時不會關閉
1.短連線
使用者端與伺服器端建立連線的時候,使用者端傳送一條訊息,使用者端與伺服器連線關閉
2.長連線
使用者端與伺服器端建立連線的時候,使用者端傳送多條訊息,使用者端與伺服器連線關閉
什麼是粘包:多次傳送的訊息,伺服器一次合併讀取msgmsg
什麼是拆包:多次傳送訊息 伺服器讀取第一條資料完整+第二條不完整資料 第二條不完整資料 Msgm sg
為什麼會造成拆包和粘包? 前提長連線、其次緩衝區
原因的造成:
Tcp協定為了能夠高效能的傳輸資料,傳送和接受時候都會採用緩衝區,必須等待緩衝區滿了以後才可以傳送或者讀取;
當我們的應用程式如果傳送的資料大於了我們的套位元組的緩衝區大小的話,就會造成了拆包。拆分成多條訊息讀取。當我們應用程式如果傳送的寫入的訊息如果小於套位元組緩衝區大小的時候
粘包與拆包產生的背景:
Tcp協定為了高效能的傳輸,傳送和接受的時候都採用了緩衝區
3. 當我們的應用程式傳送的資料大於套位元組緩衝區的時候,就會實現拆包。
4. 當我們的應用程式寫入的資料小於套位元組緩衝區的時候,多次傳送的訊息會合併到一起接受,這個過程我們可以稱做為粘包。
5. 接受端不夠及時的獲取緩衝區的資料,也會產生粘包的問題
6. 進行mss(最大報文長度)大小的TCP分段,當TCP報文長度-TCP頭部長度>mss的時候將發生拆包。
解決思路:
7. 以固定的長度傳送資料,到緩衝區
8. 可以在資料之間設定一些邊界(n或者rn)
9. 利用編碼器LineBaseDFrameDecoder解決tcp粘包的問題
常用編碼器:
利用編碼器LineBaseDFrameDecoder解決tcp粘包的問題的Java程式碼案例,核心思路就是增加邊界 n
伺服器端類 NettyServer 的修改點
serverBootstrap.group(bossGroup, workGroup).channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { // 設定我們分割最大長度為1024 socketChannel.pipeline().addLast(new LineBasedFrameDecoder(1024)); // 獲取資料的結果為string型別 socketChannel.pipeline().addLast(new StringEncoder()); //傳送資料的時候設定邊界 n socketChannel.pipeline().addLast(new ServerHandler()); } });
伺服器端類 ServerHandler 的修改點
@Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception { ByteBuf byteBuf = (ByteBuf) o; String request = byteBuf.toString(CharsetUtil.UTF_8); System.out.println("request:" + request); // 響應內容: channelHandlerContext.writeAndFlush(Unpooled.copiedBuffer("這裡是Netty伺服器端n", CharsetUtil.UTF_8)); }
使用者端的類 NettyClient 的修改點
bootstrap.group(group).channel(NioSocketChannel.class) .remoteAddress(new InetSocketAddress("127.0.0.1", 8080)) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { // 設定我們分割最大長度為1024 ch.pipeline().addLast(new LineBasedFrameDecoder(1024)); // 獲取資料的結果為string型別 ch.pipeline().addLast(new StringEncoder()); ch.pipeline().addLast(new ClientHandler()); } });
使用者端的類 ClientHandler 的修改點
@Override public void channelActive(ChannelHandlerContext ctx) throws Exception { for (int i = 0; i < 10; i++) { // 傳送資料 ctx.writeAndFlush(Unpooled.copiedBuffer("你是什麼型別的伺服器端啊?n", CharsetUtil.UTF_8)); } //使用者端發十條訊息 }
到此這篇關於Netty粘包拆包詳解及實戰流程的文章就介紹到這了,更多相關Netty粘包拆包內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45