C++版的網絡數據包解析策略(升級版)
一、數據包格式形如下圖
二、代碼
int ReceiveFromRemoteEndPoint() { int nPackageDataLength = 0; char *szPackageCleaner = NULL; char *szPackageIterator = NULL; do { char *szReceiveArray = new char[RECEIVED_BUFFER_LENGTH](); int nReceiveLength = RECEIVED_BUFFER_LENGTH; nReceiveLength = Receive(szReceiveArray, nReceiveLength, TIMEOUT); if (nReceiveLength <= 0) { Log("Recveived Time-Out(%d)...", nReceiveLength); delete[] szReceiveArray; break; } Log("Received (%d) Bytes", nReceiveLength); char *szReceive = szReceiveArray; do { if(nPackageDataLength == 0) { if(szReceive[0] != HEADER) { Log("Package Data Header-Analysis Error, Size(%d).", nReceiveLength); break; } if(nReceiveLength < PACKHEADERLENGTH) { Log("Package Data Length-Analysis Error, Size(%d).", nReceiveLength); break; } //offset HEADER length char *szPackageDataLength = szReceive + sizeof(char); //包數據的長度(不包含包頭長度) LengthResolve(szPackageDataLength, nPackageDataLength); szPackageCleaner = new char[nPackageDataLength + PACKHEADERLENGTH + 1](); szPackageIterator = szPackageCleaner; memcpy(szPackageIterator, szReceive, PACKHEADERLENGTH); szPackageIterator += PACKHEADERLENGTH; szReceive += PACKHEADERLENGTH; nReceiveLength -= PACKHEADERLENGTH; } //已接收的包數據長度 < 包數據長度 = 一個不完整的包 if(nReceiveLength < nPackageDataLength) { memcpy(szPackageIterator, szReceive, nReceiveLength); szPackageIterator += nReceiveLength; nPackageDataLength -= nReceiveLength; szReceive += nReceiveLength; nReceiveLength -= nReceiveLength; } else//(nReceiveLength >= nPackageDataLength) { //已接收的包數據長度 == 包數據長度 = 一個完整的包 //已接收的包數據長度 > 包數據長度 = 至少有一個完整的包 + 至少一個數據片段 memcpy(szPackageIterator, szReceive, nPackageDataLength); //szPackageIterator += nPackageDataLength; Resolve(szPackageCleaner, (szPackageIterator - szPackageCleaner) + nPackageDataLength); szReceive += nPackageDataLength; nReceiveLength -= nPackageDataLength; nPackageDataLength = 0; delete[] szPackageCleaner; szPackageCleaner = NULL; } }while(nReceiveLength > 0); delete[] szReceiveArray; Sleep(8); }while(IsStop);//Receiving if(szPackageCleaner != NULL) delete[] szPackageCleaner; return 0; }
三、說明
網絡數據包接收,最好是有超時機制的,比如2秒左右。
if(nReceiveLength < PACKHEADERLENGTH) { Log("Package Data Length-Analysis Error, Size(%d).", nReceiveLength); //這里會出現些問題 break; }
問題描述:
假如一個完整的數據包解析后,剩余的接收長度 < PACKHEADERLENGTH, 即包頭HEADER校驗正確,但是解析包數據長度的時接收到的數據不足以解析出
數據要接收的長度。此策略會丟棄包數據至下一個正確的包被正確解析,這個和緩沖區設置的長度是沒有直接關系的,當然長度要大於PACKHEADERLENGTH.
要解決這個問題,可以在 break; 之前保存這個數據片,並在和下次接收的拼接解析數據長度。
此策略不是最好的更不是最優的,更好的可能就在你那里呢,有你的指點我相信會更好的。