最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++實現(xiàn)TCP客戶端及服務(wù)器Recv數(shù)據(jù)篩選處理詳解

 更新時間:2022年10月09日 16:15:26   作者:中國好公民st  
這篇文章主要為大家介紹了C++實現(xiàn)TCP客戶端及服務(wù)器Recv數(shù)據(jù)篩選處理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

正文

對于一個簡單的tcp通訊這里我就不再講述了,今天主要為大家講解下,如何從::recv中篩選出一個完整包邏輯。

就簡單的以客戶端為例(服務(wù)器接收方也是同樣的邏輯),假設(shè)服務(wù)器一直在頻繁發(fā)送數(shù)據(jù),在recv函數(shù)中并不能保證每次接收的都是一個完整的包,當設(shè)置recv的緩沖區(qū)過大時,就會出現(xiàn)多個包同時接收的問題。

對于這種情況,初出茅廬的我們有時會想不到居然還有多個包共同出現(xiàn)的問題,甚至有些還沒學會如何高效的分離出一個有效的數(shù)據(jù)包。

一般在進行tcp通訊協(xié)議時,為了各個指令的區(qū)分,通常都會用以下方式進行發(fā)送,如下圖:

具體的通信協(xié)議規(guī)格可以按照各個業(yè)務(wù)需求來定義,這里只是列舉了一個簡單的例子。

在這篇文章中根據(jù)上圖中的協(xié)議格式,進行舉例講解。

協(xié)議標識測試具體
系統(tǒng)標識0x5A
源設(shè)備標識0xFCFB
預(yù)留字節(jié)假設(shè)占10個字節(jié)
源設(shè)備編碼根據(jù)連接的服務(wù)端設(shè)備編碼,假設(shè)這是是0x01(編號1)
命令字具體的業(yè)務(wù)指令,兩個字節(jié)
數(shù)據(jù)長度需要發(fā)送的數(shù)據(jù)長度
數(shù)據(jù)內(nèi)容具體業(yè)務(wù)具體內(nèi)容
校驗碼0xEF

在進行tcp通訊時,我們每條指令都是按照這種方式進行發(fā)送的,接下來,到了文章的重點部分了,該如何對接收的數(shù)據(jù)篩選?

根據(jù)流程圖可以發(fā)現(xiàn),當數(shù)據(jù)不匹配時,需要重新進行篩選,程序采用了遞歸的方式進行數(shù)據(jù)剔除。這里只是展示了內(nèi)部的流程處理,外部調(diào)用該如何呢?

int nTotalSize = 0;
while(this->JudgeValidData(vetRecvData, nTotalSize) == ture)
{
    //接收到了完整包,對包進行處理
}

代碼解析

nTotalSize:代表了一個完整數(shù)據(jù)包的總長度。

vetRecvData:recv函數(shù)接收的所有緩沖區(qū)內(nèi)容。

其實上面流程圖的內(nèi)容就是JudgeValidData()的函數(shù)處理邏輯。

對于該函數(shù)的詳細解析:

1:當Tcp緩沖區(qū)的數(shù)據(jù)小于3個字節(jié)時,不進行判斷

此時字節(jié)數(shù)據(jù)過小,無法判斷是不是當前程序中需要的

2:判斷包頭是不是一致?

上述表格中,舉例說明了包頭的定義,分別是:0x5A、0xFC、0xFB

那么,我們在判斷數(shù)據(jù)時首先要判斷包頭是否正確?包頭不正確后續(xù)也就不需要判斷了!

char ch0 = vetRecvData[0]; //系統(tǒng)標識
char ch1 = vetRecvData[1]; //標識1
char ch2 = vetRecvData[2]; //標識2
if((ch0 == 0x5A) && (ch1 == 0xFC) && (ch2 == 0xFB))
{
    //包頭正確,進行后續(xù)處理
}
else
{
    //包頭不正確,剔除數(shù)據(jù),默認剔除緩沖區(qū)的第一個字節(jié)數(shù)據(jù)
    std::vector<char>::iterator itbegin = vetRecvData.begin();
    vetRecvData.erase(itbegin);
    //重新調(diào)用當前函數(shù),遞歸判斷
    return JudgeValidData(vetRecvData, nTotalSize);
}

3:包頭匹配后,判斷是否達到了數(shù)據(jù)包的固定協(xié)議長度?

在這里說的固定協(xié)議長度,就是數(shù)據(jù)內(nèi)容之前的字節(jié),在這篇文章中,數(shù)據(jù)內(nèi)容之前有19個字節(jié),所以,當vetRecvData的數(shù)據(jù)總長度 < 19個字節(jié)時,不需要處理。

當達到固定協(xié)議長度后,說明該緩沖區(qū)中存在了有效數(shù)據(jù),那么就需要判斷實際的數(shù)據(jù)內(nèi)容是否達到了整包的標準?

4:判斷有效數(shù)據(jù)是否接收完整?

首先,需要獲取當前包需要接收的數(shù)據(jù)長度。在這里是占用三個字節(jié),分別是:16、17、18這三位

int ndatalen = (unsigned char)pThreadParam->vetRecvData[16] * 256 *256+ (unsigned char)pThreadParam->vetRecvData[17]*256 + (unsigned char)pThreadParam->vetRecvData[18];
nTotalSize = 19 + ndatalen + 1;

如果當前vetRecvData緩沖區(qū)的數(shù)據(jù) < nTotalSize,說明數(shù)據(jù)不完整,不判斷;反之,緩沖區(qū)中存在完整的數(shù)據(jù)。

5:數(shù)據(jù)校驗位判斷

最后,判斷下緩沖區(qū)完整包的最后一位是否是校驗位?

這樣,才算是一個完整的一條數(shù)據(jù)包!

到這里,就算判斷完成了,由此可以從一個大的緩沖區(qū)中抽取出有用的一組數(shù)據(jù)。

內(nèi)部的判斷邏輯講解完之后,接下來就是外部數(shù)據(jù)使用了。繼續(xù)上面的這段代碼繼續(xù)講解~

int nTotalSize = 0;
while(this->JudgeValidData(vetRecvData, nTotalSize) == ture)
{
    //接收到了完整包,對包進行處理
}

接收到一個完整包之后,數(shù)據(jù)處理過程

1:根據(jù)nTotalSize大小從緩沖區(qū)中獲取有效內(nèi)容

2:截取出剩余的緩沖區(qū)內(nèi)容,重新賦值

3:對一個完整包數(shù)據(jù)進行業(yè)務(wù)處理

將流程轉(zhuǎn)換成代碼,如下:

int nTotalSize = 0;
while (this->JudgeValidData(vetRecvData, nTotalSize) == true)
{
	//這一條數(shù)據(jù)被處理之后,使用一個臨時容器存儲 處理的 通訊數(shù)據(jù)
	std::vector<char> vetValidData;
	char* chUseData = new char[nTotalSize];
	memset(chUseData, 0, nTotalSize);
	for (int i = 0; i < vetRecvData.size(); i++)
	{
		if (i < nTotalSize)
		{
			chUseData[i] = vetRecvData[i];
		}
		else
			vetValidData.push_back(vetRecvData[i]);
	}
	//刪除 存儲所有接收字節(jié)的容器 中的數(shù)據(jù)
	vetRecvData.clear();
	vetRecvData = vetValidData; //重新更新數(shù)據(jù)信息
	//接收的是整包數(shù)據(jù)時,進行實際的數(shù)據(jù)處理
	ProcessingPancelValidData(chUseData, nTotalSize);
	delete[] chUseData;
	chUseData = nullptr;
}

以上就是C++實現(xiàn)TCP客戶端及服務(wù)器Recv數(shù)據(jù)篩選處理詳解的詳細內(nèi)容,更多關(guān)于C++ 客戶端 服務(wù)器數(shù)據(jù)篩選的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解如何在code block創(chuàng)建一個C語言的項目

    詳解如何在code block創(chuàng)建一個C語言的項目

    這篇文章主要介紹了詳解如何在code block創(chuàng)建一個C語言的項目,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • C++ std::map幾種遍歷方式(正序倒序)

    C++ std::map幾種遍歷方式(正序倒序)

    這篇文章主要介紹了C++ std::map幾種遍歷方式,包含正序遍歷和倒序遍歷,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-02-02
  • C語言數(shù)據(jù)結(jié)構(gòu)之判斷循環(huán)鏈表空與滿

    C語言數(shù)據(jù)結(jié)構(gòu)之判斷循環(huán)鏈表空與滿

    這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)之判斷循環(huán)鏈表空與滿的相關(guān)資料,希望通過本文能幫助到大家,讓大家掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-10-10
  • VS?Code?C++環(huán)境的搭建過程

    VS?Code?C++環(huán)境的搭建過程

    這篇文章主要介紹了VS?Code?C++環(huán)境的搭建,Somasegar 也告訴筆者這款編輯器也擁有對 Git 的開箱即用的支持,需要的朋友可以參考下
    2022-04-04
  • C++中protobuf?的交叉編譯使用詳解

    C++中protobuf?的交叉編譯使用詳解

    為了提高通信效率,可以采用?protobuf?替代?XML?和?Json?數(shù)據(jù)交互格式,protobuf?相對來說數(shù)據(jù)量小,在進程間通信或者設(shè)備之間通信能夠提高通信速率。下面介紹?protobuf?在?ARM?平臺上的使用,需要的朋友可以參考下
    2022-07-07
  • C語言快速實現(xiàn)掃雷小游戲

    C語言快速實現(xiàn)掃雷小游戲

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)掃雷小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • 用typedef定義類型詳細總結(jié)

    用typedef定義類型詳細總結(jié)

    用typedef可以聲明各種類型名,但不能用來定義變量,用typedef可以聲明數(shù)組類型、字符串類型、使用比較方便
    2013-10-10
  • 淺析c++中new和delete的用法

    淺析c++中new和delete的用法

    以下是對c++中new和delete的用法進行了詳細的分析介紹,需要的朋友可以過來參考下
    2013-09-09
  • C++使用ffmpeg實現(xiàn)rtsp取流的代碼

    C++使用ffmpeg實現(xiàn)rtsp取流的代碼

    這篇文章主要介紹了C++使用ffmpeg實現(xiàn)rtsp取流,文章介紹了ffmepg采用rtsp取流流程圖,CMakeLists.txt編寫方法,通過示例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-04-04
  • C++利用LuaIntf調(diào)用Lua的方法示例

    C++利用LuaIntf調(diào)用Lua的方法示例

    這篇文章主要給大家介紹了關(guān)于C++利用LuaIntf調(diào)用Lua以及利用lua-intf來調(diào)用C++函數(shù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一的參考學習價值,需要的朋友們下面來一起看看吧。
    2017-11-11

最新評論

大同县| 晋江市| 吴江市| 额济纳旗| 兴仁县| 和平区| 米易县| 九江县| 永丰县| 宜城市| 星座| 延安市| 正宁县| 巫山县| 樟树市| 盐源县| 赤城县| 南康市| 沙雅县| 渝中区| 泗水县| 佛学| 周宁县| 平乐县| 哈密市| 明溪县| 湘潭市| 专栏| 大洼县| 麻江县| 勐海县| 江北区| 东方市| 大悟县| 横山县| 固镇县| 大丰市| 盐边县| 禹城市| 大埔县| 沿河|