自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用Netty通信時(shí),遇到TCP粘包拆包問(wèn)題如何解決?答案如此簡(jiǎn)單

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
我們使用TCP協(xié)議在傳輸數(shù)據(jù)的時(shí)候,如果數(shù)據(jù)塊比較大,就會(huì)考慮將其切分。把一個(gè)大的數(shù)據(jù)包進(jìn)行切割成一個(gè)個(gè)小的數(shù)據(jù)包發(fā)送。這時(shí)候就會(huì)遇到拆包和粘包的問(wèn)題。

 [[311931]]

這篇文章會(huì)按照以下步驟進(jìn)行講解,希望對(duì)你有所收獲:

1、什么是TCP粘包拆包2、Netty中粘包問(wèn)題的問(wèn)題重現(xiàn)3、Netty中粘包問(wèn)題的解決方案

OK,在你心中有這么一個(gè)基本的脈絡(luò)之后就可以開(kāi)始今天的文章了。本系列所有的文章都會(huì)給出完整的代碼,且在電腦上真實(shí)運(yùn)行了一遍,確保無(wú)誤。

一、什么是TCP拆包和粘包

我們使用TCP協(xié)議在傳輸數(shù)據(jù)的時(shí)候,如果數(shù)據(jù)塊比較大,就會(huì)考慮將其切分。把一個(gè)大的數(shù)據(jù)包進(jìn)行切割成一個(gè)個(gè)小的數(shù)據(jù)包發(fā)送。這時(shí)候就會(huì)遇到拆包和粘包的問(wèn)題。

比如說(shuō)在這里客戶端發(fā)送了兩個(gè)數(shù)據(jù)包D1和D2到服務(wù)端,在傳輸?shù)臅r(shí)候就可能會(huì)遇到下列問(wèn)題:

 

使用Netty通信時(shí),遇到TCP粘包拆包問(wèn)題如何解決?答案如此簡(jiǎn)單

 

通過(guò)上面這張圖相信你基本上能夠理解了。不過(guò)我們?cè)谶@里還是需要稍微解釋一下:

情況1:D1和D2正常發(fā)送,每次發(fā)送一個(gè)整包。

情況2:D1數(shù)據(jù)包比較大,D2比較小。第一次發(fā)送D1的一部分,第二次發(fā)送D1剩下的和D2整包。這叫拆包。

情況2:D1和D2數(shù)據(jù)包都比較小,一次發(fā)送兩個(gè)整包,這就叫做粘包。

情況4:D1數(shù)據(jù)包比較小,D2比較大。第一次發(fā)送D1整包和D2一部分,第二次發(fā)送D2剩下的。這叫拆包。

情況5:D1和D2數(shù)據(jù)包都比較大,這時(shí)候分開(kāi)發(fā)。

為什么會(huì)出現(xiàn)這樣的問(wèn)題呢?想要解釋清楚,就必須要考慮到計(jì)算機(jī)網(wǎng)絡(luò)的相關(guān)知識(shí)了,TCP在接受數(shù)據(jù)的時(shí)候,有一個(gè)滑動(dòng)窗口來(lái)控制接受數(shù)據(jù)的大小,這個(gè)滑動(dòng)窗口你就可以理解為一個(gè)緩沖區(qū)的大小。緩沖區(qū)滿了就會(huì)把數(shù)據(jù)發(fā)送。數(shù)據(jù)包的大小是不固定的,有時(shí)候比緩沖區(qū)大,有時(shí)候小。這時(shí)候就會(huì)出現(xiàn)上面的現(xiàn)象。

下面我們使用代碼來(lái)重現(xiàn)這個(gè)現(xiàn)象。

二、問(wèn)題重現(xiàn)

1、前提準(zhǔn)備

我們是基于Springboot開(kāi)發(fā)的,因此還是和上一節(jié)一樣,首先創(chuàng)建一個(gè)Springboot的web工程,添加一下依賴:

 

使用Netty通信時(shí),遇到TCP粘包拆包問(wèn)題如何解決?答案如此簡(jiǎn)單

 

如果你沒(méi)有使用maven,下載相關(guān)jar包,直接導(dǎo)入IDE中即可。

2、服務(wù)端代碼開(kāi)發(fā)

步驟一:創(chuàng)建server類

這個(gè)server類,在上一篇文章中提到,是一個(gè)模板類,直接拿來(lái)用即可。

 

使用Netty通信時(shí),遇到TCP粘包拆包問(wèn)題如何解決?答案如此簡(jiǎn)單

 

在上面的這個(gè)代碼中同樣我們最主要的是關(guān)注ServerUAVHandler的實(shí)現(xiàn)。

步驟二:Handler的實(shí)現(xiàn)

 

使用Netty通信時(shí),遇到TCP粘包拆包問(wèn)題如何解決?答案如此簡(jiǎn)單

 

在這個(gè)類中,使用channelRead方法來(lái)讀取客戶端發(fā)送過(guò)來(lái)的信息。

(1)首先定義了一個(gè)counter,用于計(jì)算客戶端發(fā)送了多少條消息。

(2)在channelRead內(nèi)部,首先將msg轉(zhuǎn)化為ByteBuf。

(3)將buf的數(shù)據(jù)轉(zhuǎn)化為字節(jié)byte

(4)將buf的字節(jié)數(shù)據(jù)轉(zhuǎn)化為String類型,然后輸出。

(5)使用ctx的writeAndFlush方法,每收到一個(gè)客戶端的數(shù)據(jù),給對(duì)方回復(fù)一個(gè)A。別忘了還有一個(gè)換行符。

在上面的這個(gè)代碼中,最主要的就是服務(wù)端每收到一條客戶端的信息,就給其回復(fù)一條。也就是說(shuō)客戶端和服務(wù)端的消息數(shù)量應(yīng)該是一樣的。

3、客戶端代碼開(kāi)發(fā)

步驟一:創(chuàng)建client類

 

使用Netty通信時(shí),遇到TCP粘包拆包問(wèn)題如何解決?答案如此簡(jiǎn)單

 

同樣的代碼的邏輯在上一篇文章中已經(jīng)說(shuō)了,我們還是最關(guān)注的事件處理類Handler。

步驟二:Handler實(shí)現(xiàn)

 

使用Netty通信時(shí),遇到TCP粘包拆包問(wèn)題如何解決?答案如此簡(jiǎn)單

 

這個(gè)客戶端的Handler看起來(lái)有點(diǎn)多,一共有兩個(gè)方法,channelActive和channelRead。

(1)channelActive里面使用for循環(huán)給服務(wù)器發(fā)送了100條,我愛(ài)你。每次發(fā)送還有在末尾添加一個(gè)換行符。

(2)channelRead里面接受服務(wù)器返回的消息。

按道理來(lái)講,客戶端給服務(wù)端發(fā)送了100條數(shù)據(jù),那么服務(wù)端也會(huì)返回回來(lái)100條。我們來(lái)驗(yàn)證一下。

 

使用Netty通信時(shí),遇到TCP粘包拆包問(wèn)題如何解決?答案如此簡(jiǎn)單

 

這里輸出的是服務(wù)端的信息,從上面的輸出結(jié)果你就會(huì)發(fā)現(xiàn),其實(shí)客戶端的“我愛(ài)你”都被黏在了一塊。本來(lái)100條但是現(xiàn)在卻只有17條了,這就是發(fā)生了粘包現(xiàn)象。

如何來(lái)解決呢?下面我們看看。

三、粘包問(wèn)題解決

解決的思路很簡(jiǎn)單,也就是每次發(fā)送一個(gè)數(shù)據(jù)包的時(shí)候,添加一個(gè)標(biāo)識(shí)符,讀的時(shí)候一直讀到這個(gè)標(biāo)識(shí)符才表示一個(gè)完整的數(shù)據(jù)包。在上面我們添加的是line.separator,也就是換行符“\n”。

1、服務(wù)端server類更改。

 

使用Netty通信時(shí),遇到TCP粘包拆包問(wèn)題如何解決?答案如此簡(jiǎn)單

 

2、服務(wù)端Handler類更改

 

使用Netty通信時(shí),遇到TCP粘包拆包問(wèn)題如何解決?答案如此簡(jiǎn)單

 

3、客戶端Client更改

 

使用Netty通信時(shí),遇到TCP粘包拆包問(wèn)題如何解決?答案如此簡(jiǎn)單

 

4、客戶端Handler更改

 

使用Netty通信時(shí),遇到TCP粘包拆包問(wèn)題如何解決?答案如此簡(jiǎn)單

 

客戶端和服務(wù)端改的地方都一樣,不過(guò)還是貼了出來(lái),現(xiàn)在我們?cè)龠\(yùn)行一波。

 

使用Netty通信時(shí),遇到TCP粘包拆包問(wèn)題如何解決?答案如此簡(jiǎn)單

 

看到?jīng)]是不是很神奇。我們來(lái)分析一下我們都修改了什么。

好像我們就只是在server和client類添加了兩個(gè)類,一個(gè)是LineBasedFrameDecoder,一個(gè)是StringDecoder,其他的都是直接刪除,這兩個(gè)類有什么作用呢?

(1)LineBasedFrameDecoder的作用是在讀取數(shù)據(jù)的時(shí)候,一直讀到是否含有換行符“\n”或者是“\r\n”。如果讀到了就表示該結(jié)束了。因此就拿到了這一行的數(shù)據(jù)包。

(2)StringDecoder用于對(duì)之前LineBasedFrameDecoder讀取的這一行數(shù)據(jù)包進(jìn)行解碼。將對(duì)象轉(zhuǎn)換為字符串。

OK,好像他們倆搭配,干活真不累,現(xiàn)在我們終于可以解決粘包的問(wèn)題了,但是同時(shí)也出現(xiàn)了一個(gè)新的問(wèn)題,那就是如果我們的標(biāo)識(shí)符不是換行符“\n”或者是“\r\n”又該怎么辦呢?幸好Netty同樣為我們提供了幾種其他的解碼器,叫做DelimiterBasedFrameDecoder和FixedLengthFrameDecoder,前面這個(gè)可以自動(dòng)完成以分隔符做結(jié)束標(biāo)志的消息,后面這個(gè)可以自動(dòng)完成對(duì)定長(zhǎng)消息的解碼。都可以解決粘包拆包問(wèn)題。

 

責(zé)任編輯:武曉燕 來(lái)源: 今日頭條
相關(guān)推薦

2021-07-15 10:35:16

NettyTCPJava

2020-12-23 07:53:01

TCP通信Netty

2024-08-16 21:47:18

2019-10-17 11:06:32

TCP粘包通信協(xié)議

2024-06-03 08:09:46

2024-12-19 11:00:00

TCP網(wǎng)絡(luò)通信粘包

2021-03-09 22:30:47

TCP拆包協(xié)議

2025-04-10 10:15:30

2022-04-28 08:38:09

TCP協(xié)議解碼器

2020-10-15 18:31:36

理解Netty編解碼

2019-08-15 07:43:38

TCP網(wǎng)絡(luò)協(xié)議丟包

2021-01-13 10:18:29

SocketNetty粘包

2020-03-10 08:27:24

TCP粘包網(wǎng)絡(luò)協(xié)議

2019-10-25 00:32:12

TCP粘包Netty

2019-10-24 07:35:13

TCP粘包Netty

2024-10-12 18:16:27

2021-10-08 09:38:57

NettyChannelHand架構(gòu)

2020-04-09 11:08:30

PyFlinkJAR依賴

2015-04-01 10:26:32

開(kāi)發(fā)中文亂碼問(wèn)題

2024-01-10 09:44:11

MySQL死鎖
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)