0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何讓接收端知道發(fā)送端將要發(fā)送的字節(jié)流長度?

冬至配餃子 ? 來源:多蘭多 ? 作者:Toranto ? 2022-08-19 09:33 ? 次閱讀

粘包現(xiàn)象展示

一上來就枯燥的文字,難免容易犯困,所以我先演示一下粘包現(xiàn)象:

pYYBAGL-5cuAOVptAACt-k3cEww678.pngpYYBAGL-5dKAQaAaAACFAIai1xo613.png

我們的預期是,服務端打印出hello,I am Toranto這兩個字符串,兩個字符串經(jīng)編碼之后的字節(jié)總長度為17個字節(jié),但是我們看結果:

pYYBAGL-5eiAZO4uAAClEv3pYXI844.png

ps:b''是表示字節(jié)的意思,和我們之前用的f''(format)格式化用法是一樣的,單、雙、三引號一樣。可以了解一下:

pYYBAGL-5fmAJFgWAADuKMsMuyQ976.png

好了回歸粘包現(xiàn)象,我們看到上圖,我們采用兩次接收數(shù)據(jù)的方式,兩次都接收20個字節(jié),但是發(fā)送端發(fā)送的兩次總字節(jié)只有17個字節(jié)長度,所以,tcp基于流式的協(xié)議,會先發(fā)送第一段字節(jié)到一個緩沖區(qū),如果時間間隔很短,則tcp會等第二段字也發(fā)送到這個緩沖區(qū)再統(tǒng)一發(fā)送到接收端這邊,兩次內容的粘合沒有達到我們預期的效果,這就是粘包現(xiàn)象。

粘包

粘包是一種現(xiàn)象,而且只有tcp會出現(xiàn)粘包現(xiàn)象,udp不會,這是基于tcp的

流式傳輸

導致的,tcp是傳輸數(shù)據(jù)流。

tcp會將數(shù)據(jù)量較小,且發(fā)送時間間隔較短的數(shù)據(jù)一起打包發(fā)送,那么這里所講的時間較短是相比網(wǎng)絡延遲來說的。比如我們兩次發(fā)送間隔為0.00001s,那么網(wǎng)絡延遲為0.001s,這個時候兩次的數(shù)據(jù)就會打包發(fā)送,這是一種優(yōu)化機制,但也就是這個優(yōu)化機制導致粘包現(xiàn)象。

首先我們需要了解一下socket收發(fā)數(shù)據(jù)的原理:

pYYBAGL-5hOAUFCWAAB4BXjjpO0413.png


發(fā)送端可以是1K1K地發(fā)送數(shù)據(jù),而接收端的應用程序可以兩K兩K地提走數(shù)據(jù),當然也有可能一次提走3K或6K數(shù)據(jù),或者一次只提走幾個字節(jié)的數(shù)據(jù),也就是說,應用程序所看到的數(shù)據(jù)是一個整體,或說是一個流(stream),一條消息有多少字節(jié)對應用程序是不可見的,因此TCP協(xié)議是面向流的協(xié)議,這也是容易出現(xiàn)粘包問題的原因。

UDP是面向消息的協(xié)議,每個UDP段都是一條消息,應用程序必須以消息為單位提取數(shù)據(jù),不能一次提取任意字節(jié)的數(shù)據(jù),這一點和TCP是很不同的。怎樣定義消息呢?可以認為對方一次性write/send的數(shù)據(jù)為一個消息,需要明白的是當對方send一條信息的時候,無論底層怎樣分段分片,TCP協(xié)議層會把構成整條消息的數(shù)據(jù)段排序完成后才呈現(xiàn)在內核緩沖區(qū)。

例如基于tcp的套接字客戶端往服務端上傳文件,發(fā)送時文件內容是按照一段一段的字節(jié)流發(fā)送的,在接收方看來,根本不知道該文件的字節(jié)流從何處開始,在何處結束。

所謂粘包問題主要還是因為接收方不知道消息之間的界限,不知道一次性提取多少字節(jié)的數(shù)據(jù)所造成的。

此外,發(fā)送方引起的粘包是由TCP協(xié)議本身造成的,TCP為提高傳輸效率,發(fā)送方往往要收集到足夠多的數(shù)據(jù)后才發(fā)送一個TCP段。若連續(xù)幾次需要send的數(shù)據(jù)都很少,通常TCP會根據(jù)優(yōu)化算法把這些數(shù)據(jù)合成一個TCP段后一次發(fā)送出去,這樣接收方就收到了粘包數(shù)據(jù)。

粘包解決

很遺憾,socket并沒有給我們提供內置解決方法。

那我們需要如何解決?

問題的根源在于,接收端不知道發(fā)送端將要發(fā)送的字節(jié)流的長度。

我們可以基于此點想解決辦法,如何讓接收端知道發(fā)送端將要發(fā)送的字節(jié)流長度(提前獲知)?

我們可以在發(fā)送端寫一個提前告知的代碼,并且在接收端循環(huán)判定,是否達到預定字節(jié)流長度,達到了再一并打印出來:

發(fā)送端和接收端(關鍵)要結合起來看:

poYBAGL-5liADeynAACWEief7aM603.pngpoYBAGL-5maASjQyAAC99PDfsRo576.png

接下來我把源碼放上來,我加了一些判斷條件:

poYBAGL-5pyAGUpLAAEN4Em8_V4145.pngpoYBAGL-5qKADGyrAACxqV0zfe0603.pngpYYBAGL-5qeAaPxNAADr_s6XptU956.png

演示一下結果:

pYYBAGL-5-uAA8XNAAFN4_KPLZM724.pngpYYBAGL-5_CAFcRvAABXEcoRNqU369.png



審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 編解碼
    +關注

    關注

    1

    文章

    140

    瀏覽量

    19564
  • 字符串
    +關注

    關注

    1

    文章

    567

    瀏覽量

    20443
  • 網(wǎng)絡編程

    關注

    0

    文章

    66

    瀏覽量

    10048
  • TCP協(xié)議
    +關注

    關注

    1

    文章

    91

    瀏覽量

    12050
收藏 人收藏

    評論

    相關推薦

    FPGA高速收發(fā)器的GTX發(fā)送解析

    每一個收發(fā)器擁有一個獨立的發(fā)送,發(fā)送有PMA(Physical Media Attachment,物理媒介適配層)和PCS(PhysicalCoding Sublayer,物理編碼
    的頭像 發(fā)表于 11-20 11:27 ?6457次閱讀
    FPGA高速收發(fā)器的GTX<b class='flag-5'>發(fā)送</b><b class='flag-5'>端</b>解析

    ZYNQ進階:PLUART 發(fā)送設計案例

    在 ZYNQ進階之路2 中我們講解了PLPWM呼吸燈的設計,本節(jié)我們講解PL實現(xiàn)串口UART的發(fā)送設計; 首先新建一個串口發(fā)送的工程,工程建立在ZYNQ進階之路1中已經(jīng)講述,這里不
    的頭像 發(fā)表于 11-25 17:26 ?3473次閱讀
    ZYNQ進階:PL<b class='flag-5'>端</b>UART <b class='flag-5'>發(fā)送</b>設計案例

    HDMI信號的接收發(fā)送與PD的DFP和UFP有對應關系嗎?

    HDMI信號的接收發(fā)送與PD的DFP和UFP有對應關系嗎? 例如:一作為HDMI的接收
    發(fā)表于 02-29 07:46

    TCP通信的接收發(fā)送字符串的這個原理是什么???謝謝!

    一個是 服務器的 接收部分,一個是 客戶發(fā)送部分。發(fā)送部分是不是: 先發(fā)送字符串的 長度,
    發(fā)表于 05-06 15:52

    can總線發(fā)送大于八個字節(jié)數(shù)據(jù)代碼怎實現(xiàn)

    將要發(fā)送IP報文所以將要發(fā)送的數(shù)據(jù)遠遠大于8個字節(jié)……現(xiàn)在的思路就是構造一個新的數(shù)據(jù)幀,包含頭和尾還有數(shù)據(jù)的
    發(fā)表于 06-17 14:32

    LWIP UDP如何發(fā)送長度超過1500字節(jié)的數(shù)據(jù)?

    環(huán)境:STM32F7 + FREERTOS + LWIP UDP在使用UDP發(fā)送數(shù)據(jù)時,發(fā)現(xiàn)發(fā)送長度比較大的數(shù)據(jù)時PC的網(wǎng)絡助手收不到數(shù)據(jù),一直找BUG,最后看到網(wǎng)上說UDP
    發(fā)表于 05-23 19:28

    如何解決lwip的netconn客戶發(fā)送問題

    我的板子做客戶,用的lwip,現(xiàn)在在與服務器連接成功后,發(fā)送有個問題1,在網(wǎng)絡調試助手中設置20ms不停發(fā)送1字節(jié),板子客戶
    發(fā)表于 07-15 04:36

    CC2500不能接收發(fā)送數(shù)據(jù)

    。發(fā)送前TXBYTES能讀到寫進TX_FIFO中的字節(jié)數(shù),發(fā)送完成后讀到的是0.發(fā)送接收兩邊
    發(fā)表于 03-27 10:22

    如何在發(fā)送發(fā)送逗號?

    將使用逗號檢測和對齊模塊。但現(xiàn)在我有點困惑。如何在發(fā)送發(fā)送逗號? 如果我只是使用GTP傳輸PRBS并接收PRBS,我是否必須使用逗號來對齊字節(jié)
    發(fā)表于 06-10 08:56

    如何兩片89C51實現(xiàn)串行通信,發(fā)送將0~f循環(huán)發(fā)送接收并在接收顯示?

    如何兩片89C51實現(xiàn)串行通信,發(fā)送將0~f循環(huán)發(fā)送接收并在
    發(fā)表于 09-30 06:27

    在消息列隊中初始化時怎么知道發(fā)送消息的長度

    問題:假設串口1接收了200個字節(jié),串口接收完成后,通過消息列隊把這200個數(shù)據(jù)發(fā)送給處理線程1,線程1怎么知道串口中斷發(fā)過來的是200個
    發(fā)表于 03-24 09:26

    載波發(fā)送接收端接口電路

    接口電路的實現(xiàn)  根據(jù)上述的理論分析與建立的數(shù)學模型,可設計出低壓電力線通信發(fā)送的接口電路,如圖2所示。?
    發(fā)表于 10-13 13:54 ?2082次閱讀
    載波<b class='flag-5'>發(fā)送</b><b class='flag-5'>端</b>與<b class='flag-5'>接收</b>端接口電路

    基于系數(shù)可調FFE的10Gb_s發(fā)送的設計

    基于系數(shù)可調FFE的10Gb_s發(fā)送的設計_陳功
    發(fā)表于 01-07 21:39 ?2次下載

    STM32F4發(fā)送接收長度數(shù)據(jù)的判斷

    STM32F4 串口收發(fā)使用DMA還是很方便的。但是配置DMA時需要配置數(shù)據(jù)長度,這一點對于發(fā)送來說可以預估計自己發(fā)送長度來配置DMA發(fā)送
    發(fā)表于 11-08 16:25 ?6321次閱讀

    字節(jié)流和字符流有什么區(qū)別?看完就知道!

    字節(jié)流和字符流有什么區(qū)別?看完就知道! 字節(jié)流和字符流是Java I/O系統(tǒng)中的兩個重要概念,用于處理輸入和輸出的數(shù)據(jù)。 首先,字節(jié)流是以字節(jié)
    的頭像 發(fā)表于 12-09 14:57 ?1352次閱讀