研究網狐的内核框架發現經常有以下錯誤:
SocketEngine Index=0,RountID=18,OnRecvCompleted 發生“數據包效驗碼錯誤”異常
因字節跳動股票爲不是必現的問題,非常不好排查,而網狐的東西也相對較穩定,不知如何下手,然後就仔細看内核相關的代碼,看到了内存數據隊列;WHDataQueue隊列的實現其實還是非常巧妙的,用變量标志就在一個内存塊上實現了環形的隊列,越是巧妙的東西,就越容易出錯,也長度單位換算口訣就越需要打磨,雖然研究網狐框架代碼内存條哪個牌子好的人很多,但不知道爲什麽我在網上各種找資料,就是找不到這個問題的解決方案,可能這是個偶發的問題,在服務端跑的時候,也極少出現,就算出現也隻是影響某個玩家,所以問題就被數據漫遊是什麽意思隐藏了吧。
int nIndex = 0; TCHAR szInfo[4096] = TEXT(""); int nLen = 0; //寫入0字節, 讓gDataQueue内存塊大小爲 40, 實際上是寫入4字節,因爲裏面還有個數據頭 rand_str(szInfo, 0); gDataQueue.InsertData(++nIndex, szInfo, 0); tagDataHead head; //取出,之後 m_dwDataQueryPos 變成4 gDataQueue.DistillData(head, szInfo, sizeof(szInfo)); //寫入16個字節 rand_str(szInfo, 7); nLen = CountStringBuffer(szInfo); gDataQueue.InsertData(++nIndex, szInfo, nLen); std::cout << nLen <<", " << nIndex << endl; //取出,之後 m_dwDataQueryPos 變成24, m_dwDataSize=0 gDataQueue.DistillData(head, szInfo, sizeof(szInfo)); std::cout << head.wDataSize << ", " << head.wIdentifier<< endl; std::cout << "" << endl; //寫入20字節, //因爲寫入到結束位置,寫入位置+寫入長度大于總長,查詢位置大于寫入長度, //基于以上三點原因,說明可以寫從頭開始再入,所以會把 m_dwInsertPos 設置爲0 rand_str(szInfo, 9); nLen = CountStringBuffer(szInfo); gDataQueue.InsertData(++nIndex, szInfo, nLen); std::cout << nLen << ", " << nIndex << endl; //再寫入10字節 rand_str(szInfo, 3); nLen = CountStringBuffer(szInfo); //寫入10字節之後, //實際上gDataQueue就變成m_dwDataQueryPos = 24(因爲沒有讀取操作) //m_dwDataSize = 38, m_dwInsertPos = 38 //到這一步貌似也還沒有問題,但是如果後續的操作不是讀取而是繼續寫入,那麽就有出現問題 gDataQueue.InsertData(++nIndex, szInfo, nLen); std::cout << nLen << ", " << nIndex << endl; rand_str(szInfo, 28); nLen = CountStringBuffer(szInfo); //爲了測試問題,這一步繼續寫入,因爲總長是40,再寫入,則會重新分配空間 //重新分配空間時,需要将原有内存數據拷貝到新内存,問題就出現這個拷貝上,步驟如下: //1. 判斷是否存在末尾還有未讀完的數據:m_dwTerminalPos-m_dwDataQueryPos=14 //2. 先将末尾數據拷貝:CopyMemory(pNewQueueServiceBuffer, m_pDataQueueBuffer + m_dwDataQueryPos, dwPartOneSize); //3. 再從頭開始拷貝:CopyMemory(pNewQueueServiceBuffer + dwPartOneSize, m_pDataQueueBuffer, m_dwInsertPos); //這個步驟理論上是沒有錯的,但是結合上面的寫入數據的順序,則忽略了一個細節: 寫入的數據長度已經覆蓋了查詢标記 gDataQueue.InsertData(++nIndex, szInfo, nLen); std::cout << nLen << ", " << nIndex << endl; std::cout << "" << endl; gDataQueue.DistillData(head, szInfo, sizeof(szInfo)); std::cout << head.wDataSize << ", " << head.wIdentifier << endl; gDataQueue.DistillData(head, szInfo, sizeof(szInfo)); std::cout << head.wDataSize << ", " << head.wIdentifier << endl; gDataQueue.DistillData(head, szInfo, sizeof(szInfo)); std::cout << head.wDataSize << ", " << head.wIdentifier << endl;
修複代碼:
在bool CWHDataQueue::Rectify數據漫遊是什麽意思Buffer(DWORD dwNeedSize)函數中加上一行:
try { //緩沖判斷 if ((m_dwDataSize+dwNeedSize)>m_dwBufferSize) throw 0; //重新開始 if ((m_dwInsertPos==m_dwTerminalPos)&&((m_dwInsertPos+dwNeedSize)>m_dwBufferSize)) { if (m_dwDataQueryPos>=dwNeedSize) m_dwInsertPos=0; else throw 0; } //緩沖判斷 if ((m_dwInsertPos<m_dwTerminalPos)&&((m_dwInsertPos+dwNeedSize)>m_dwDataQueryPos)) throw 0; //頭追上尾或尾追上頭 if (m_dwInsertPos + dwNeedSize > m_dwDataQueryPos && m_dwDataQueryPos >= m_dwInsertPos) { //尾追上頭 if (m_dwDataSize > 0) throw 0; } }
網狐棋牌框架-WHDataQueue隊列的問題原文鏈接:https://qipaiyuanmaxiazai.com/5553.html,轉載請注明出處~~~
評論0