一友人做游戏服务器,涉及通信模块和业务模块,在软件行业也算个老兵了,也搞c++n多年了,对于软件开发也有自己的一些想法和心得,将其代码与我分享,让我观赞一下。
c++是我从业一来一直信奉的开发工具,虽然近些年一直用python来搞定应用需求,但关键时刻还必须是c++搞定, 所以c++的程序代码能hold住的。
我知道写通信部分代码的关键点在哪里,比如: 性能、安全、完整性、模块化设计和处理,所以有针对性的去检查友人的代码,当看到这个函数的时候,致命的错误来了:
分别在于: 第 13,20行 ,其分别会导致服务器崩溃和不响应
1
2 tagPack* CClient::getRecvPack()
3 {
4 uv_mutex_lock(&_lockrecv);
5 tagPack *t = NULL;
6 if(_recvPackLenght < 4)
7 {
8 _recvOver = true;
9 uv_mutex_unlock(&_lockrecv);
10 return t;
11 }
12 tagPack* tmp = _lsRecvBuf.front();
13 unsigned int size = *(unsigned int*)&tmp->pack[0];
14 if(_recvPackLenght < size)
15 {
16 _recvOver = true;
17 uv_mutex_unlock(&_lockrecv);
18 return t;
19 }
20 BYTE* mem = new BYTE[size];
21
22 unsigned int index = 0;
23 unsigned int needSize = size;
24 while(true)
25 {
26 if(tmp->size < needSize)
27 {
28 memcpy(&mem[index], tmp->pack, tmp->size);
29 needSize -= tmp->size;
30 index += tmp->size;
31 delete tmp;
32 _lsRecvBuf.pop_front();
33 }
34 else if(tmp->size == needSize)
35 {
36 memcpy(&mem[index], tmp->pack, tmp->size);
37 needSize -= tmp->size;
38 index += tmp->size;
39 delete tmp;
40 _lsRecvBuf.pop_front();
41 }
42 else
43 {
44 memcpy(&mem[index], tmp->pack, needSize);
45 memcpy(tmp->pack, &tmp->pack[needSize], tmp->size - needSize);
46 tmp->size -= needSize;
47
48 needSize = 0;
49 }
50
51 if( needSize == 0 )
52 {
53 t = new tagPack(size);
54 t->addBytes(mem, size);
55 t->_sock = _sock;
56 delete []mem;
57 _recvPackLenght -= t->size;
58 break;
59 }
60 tmp = _lsRecvBuf.front();
61 }
62 uv_mutex_unlock(&_lockrecv);
63
64 return t;
65 }
13行: 开发者直接将缓存内存地址作为接收和发送地址,没考虑 字节序问题 (htonl,ntohl)
20行: 逻辑不严密,如果用户发送4个字节数据,且均为0 ,结果就是服务器崩溃。
所以codereview还是很重要的,特别是将c++应用在性能,效率关键部位的代码。