第一次實質性的接觸socket通訊方面的工做,因此遇到的問題還真很多,寫篇博客記錄一下,提高下記憶。ios
需求是經過私有協議進行二進制數據的傳輸,必須保證數據包不能被丟失,因此選擇tcp的socket進行通訊。安全
1. 遇到的第一個問題是客戶端與服務端的socket通訊沒有保持持續的鏈接狀態服務器
這個是一個想固然的錯誤。想固然的覺得TCP是有鏈接的通訊,可是你若是長時間不通訊,服務端一直保持着通訊,這對服務器資源是一種極大的浪費。客戶端與服務端的鏈接是須要佔用必定資源的,而服務端的資源是有限的。若是一直保持鏈接狀態,那麼你的服務器的性能確定是有問題的。socket
解決這個問題的辦法是保活。服務端發送心跳包,客戶端接受到以後進行迴應。客戶端告訴服務器,還在線,不要斷開鏈接。若是客戶端長時間沒有迴應,服務器斷開與此客戶端的鏈接,減小資源佔用。tcp
2. 二進制文件的讀寫問題性能
第一次嘗試讀取二進制文件採起了分段讀取的方式。測試過程當中發現一個很大的問題:文件讀取到部分就會中斷讀取。debug下,得出是讀取到了空字符('\0')。這個直接致使一次讀取到內容在發送前丟失,甚至有些狀況下會有空字符,客戶端接受時會產生崩潰現象。測試
既然分段不行,就乾脆所有讀取,而後在分段發送。boost.asio庫支持對vector包裝發送,分段發送時,把一塊二進制流拷貝到vector中,而後總體發送。加密
3. 提升二進制流的傳輸效率spa
直接傳輸二進制流不是一個高效的行爲,也不是一個安全的行爲。直接發送一個二進制流很容易被截獲,從而致使信息泄露。debug
提升二進制流傳輸效率的辦法就是加密壓縮再發送。服務器加密壓縮,客戶端解密解壓縮。可採起兩種方式:
1)總體壓縮,分段發送
2)分段壓縮,分段發送
要求不是很高的話,採起方式一比較好。簡單粗暴。。
貼一些代碼,總體讀取二進制文件的:
先是C++的:
1 string fileName = "D:/XtAmpClient/XtAmpTradeClient_x64_3.0.1.14473.exe"; 2 ifstream ifs(fileName, ios_base::binary); 3 4 filebuf* pbuf = ifs.rdbuf(); 5 int size = pbuf->pubseekoff(0, ios_base::end, ios_base::in); 6 pbuf->pubseekpos(0, ios_base::in); 7 8 char* buf = new char[size]; 9 pbuf->sgetn(buf, size); 10 ifs.close(); 11 delete []buf;
最後是C的:
1 const char* fileName = "D:/XtAmpClient/XtAmpTradeClient_x64_3.0.1.14473.exe"; 2 FILE* fp = fopen(fileName, "rb"); 3 if (NULL == fp) 4 { 5 cout << "open file failed" << endl; 6 return ; 7 } 8 9 fseek(fp, 0, SEEK_END); 10 long size = ftell(fp); 11 rewind(fp); 12 13 char* buffer = (char*)malloc(sizeof(char) * size); 14 if (NULL == buffer) 15 { 16 cout << "malloc failed" << endl; 17 return ; 18 } 19 20 int ret = fread(buffer, 1, size, fp); 21 if (ret != size) 22 { 23 cout << "reading failed" << endl; 24 return ; 25 } 26 27 fclose(fp); 28 free(buffer);
性能上C比C++好一點點,可是C++的代碼明顯更簡潔。