【1 背景】
在Socket通信中,要傳輸結構化的資料或者要進行協定資料傳輸的時候,發送端必須要構造結構體進行資料傳輸。
接收端也必須通過同樣的結構體進行解析。
但Socket傳輸結構體資料時候,稍有不慎就會出現:1)解析資料出錯;2)接收資料不完整;3)解析為亂碼等的Bug。
【2 舉例】
如下是接收端解析資料為亂碼甚至崩潰的一類常見錯誤。
結構體也就是一段連續的記憶體。 但是類似如下的結構體:
typedef struct _PER_SPIDER_INFO
{
UINT nTimeDelay;
UINT nRtnCode;
UINT nUrlPageLen;
char* pszUrlPage;
}PER_SPIDER_INFO;
不能直接通過傳輸的。
【3 根本原因】
如下:
1)結構體成員pszUrlPage是指針,指向的是結構體以外的記憶體位址,也就是在結構體PER_SPIDER_INFO外的非連續的位址空間。
2)如果僅傳輸pszUrlPage,也就是傳輸了一個位址,在目前程序空間是可以索引到對應的值。但是一旦通過Socket實作網絡傳輸,即出現了跨程序、跨網絡的傳輸,一個位址傳輸過去,極大可能甚至100%會讀到我們不想要的位址空間,讀取的值也會出錯。一旦該位址空間不允許讀,則會導緻程式崩潰。(如下圖所示)
3)可以傳輸,正如2)所說,但一旦接受後對方機器無法正确解析,甚至程式崩潰。

【4 Bug解決步驟路演】
Step1: 縮小範圍,隻傳輸int資料,ok;但單包含了字元串指針就不可以;基本鎖定是字元串這裡除了問題。
Step2:字元串指針換成字元串數組,Bug不再出現。說明至少是連續記憶體這裡出了問題。期間,懷疑動态配置設定記憶體malloc()以及strcpy,memcpy,傳輸結構體資料的長度出了問題,花了近3個小時排查。
Step3:進而換成給定長度(大小結合項目定)的字元串數組,Bug解決掉。
【5 修正後】
typedef struct _PER_SPIDER_INFO
{
UINT nTimeDelay;
UINT nRtnCode;
UINT nUrlPageLen;
char szUrlPage[MAX_URL_PATH]
}PER_SPIDER_INFO;
就可以通過socket傳輸了。
【6反思與思考】
但是不是包含指針的就不能傳輸了呢?不是的,隻要記憶體處理的得當也是可以的。回頭有示例再附上解析。
未完待續。
作者:銘毅天下
轉載請标明出處,原文位址:
http://blog.csdn.net/laoyang360/article/details/47342541