一友人做游戲服務器,涉及通信模塊和業務模塊,在軟件行業也算個老兵了,也搞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++應用在性能,效率關鍵部位的代碼。