从上周开始,当大规模测试商城购买道具时,偶尔会出现客户端收不到消息的情况。一开始怀疑是逻辑层出了问题,排查3天后,把问题定位在了底层的
发送网络消息这块有问题。大家都知道分析网络包是一件非常痛苦的事情,主要是费眼。
我抓取了一下包,进行大致了分析:
// 发送方
data=0 18 6 5E 0 FFFFFFD5 5B 2E 53 5D FFFFFFCA 52 12 FFFFFFB7 FFFFFF8E 7D 1D 40 FFFFFFBC 4E 6B 46 59 FFFFFFFA C FFFFFFDF FFFFFF92 37 FFFFFFE0 3F
//接收方
data=46 59 FFFFFFFA C FFFFFFDF FFFFFF92 37 FFFFFFE0 3F 5D FFFFFFCA 52 12 FFFFFFB7 FFFFFF8E 7D 1D 40 FFFFFFBC 4E 6B 46 59 FFFFFFFA C FFFFFFDF FFFFFF92 37 FFFFFFE0 3F
data=C FFFFFFDF FFFFFF92 37 FFFFFFE0 3F C FFFFFFDF FFFFFF92 37 FFFFFFE0 3F C FFFFFFDF FFFFFF92 37 FFFFFFE0 3F C FFFFFFDF FFFFFF92 37 FFFFFFE0 3F C FFFFFFDF FFFFFF92 37 FFFFFFE0 3F
发送方的数据和我程序解析后的数据是一致的,但是接收方的数据出错了,经过多次的对比发现,发送方和接收方的数据有交集,而且有一定规律的偏移。
最终的定论接收方在拆包和粘包时处理数据出错了。
其中有一段代码如下:
memcpy(m_pSrc, &m_pSrc[nLen], nOffset);
引用上述的网络包为用例如下:
拷贝前的数据为:
data=46 59 FFFFFFFA C FFFFFFDF FFFFFF92 37 FFFFFFE0 3F 5D FFFFFFCA 52 12 FFFFFFB7 FFFFFF8E 7D 1D 40 FFFFFFBC 4E 6B 46 59 FFFFFFFA C FFFFFFDF FFFFFF92 37 FFFFFFE0 3Fm_pSrc定义为 char m_pSrc[1024*10];
当nLen=6, nOffset=24,调用
memcpy(m_pSrc, &m_pSrc[nLen], nOffset);
拷贝后的数据为:
data=C FFFFFFDF FFFFFF92 37 FFFFFFE0 3F C FFFFFFDF FFFFFF92 37 FFFFFFE0 3F C FFFFFFDF FFFFFF92 37 FFFFFFE0 3F C FFFFFFDF FFFFFF92 37 FFFFFFE0 3F C FFFFFFDF FFFFFF92 37 FFFFFFE0 3F这里我均打印出了m_pSrc的前30个字节的数据。
对,问题就是出在这里了,至于为什么,现在还没有时间去仔细排查,据说是memcpy的一个使用陷阱,我换了一种方式移动数据后,貌似问题就解决了。
等我确定原因后,把答案补充在这里,目前紧张测试中。
眼睛盯着屏幕的0XABCDEF,都快花眼了,这真是一件苦逼的活。。。。
2012-09-11
第一次更新:
用memmove取代memcpy之后,问题得到了解决,但不符合常理,因为这里基本否定了地址重叠的情况,摸索中。。。
第二次更新:
左思右想,没有想到结论的前提下,我照抄了memcpy函数,给他起了个别名
void * my_memcpy (void *dest, const void *src, size_t len)
{
char *d = (char*)dest;
const char *s = (const char*)src;
while (len--)
*d++ = *s++;
return dest;
}
改成:my_memcpy(m_pSrc, &m_pSrc[nLen], nOffset);
后,运行结果正常,我了个擦,到底发生了什么,难道系统函数不是这么写的?
付上版本号:
Linux version 2.6.32-38-generic-pae (buildd@rothera) (gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) ) #85-Ubuntu SMP Wed Jan 25 15:37:46 UTC 2012