【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