網絡數據(socket)傳輸總結


環境限定:TCP/IP下的socket網絡傳輸;C/C++開發語言,32/64位機。

目前有兩種方式對數據進行傳輸:1)字符流形式,即將數據用字符串表示;2)結構型方式,即將數據按類型直接傳輸。

1)的方式保證所有的數據都是清晰的字符串明文,沒有平台不一致問題,但傳輸的數據不定長,復合數據類型(如struct)的解析不方便。
2)的方式保證數據長度固定/可控,方便對接受到數據的解析;但前提是要考慮平台不一致問題,如字節序、對齊位寬、數據類型等;


兩種數據傳輸方式應用時的注意點:
1)字符流形式 -- 需要協商好數據的解析方式,考慮到數據不定長可能導致的問題。
2)結構形式 -- 主要注意平台不一致導致的問題。


字符流傳輸方式相對簡單、安全,以結構方式傳輸則不同。結構形式傳輸數據時,要檢查下面各點:
1)首先要清楚是否有機器位寬不一致的情況,如32位機和64位機。如果位寬不一致,則避免傳輸表示方式不一致的數據類型,如long、float型在32位了64位下表示方式不一致,會導致數據解析錯誤。
2)確認通信雙方的對齊位寬一致,或自己保證傳輸的數據結構在對齊調整后不會產生大小不一致。如果收發雙方的對齊方式分別是按4和8字節對齊,則需要在程序中明確制定對齊位寬;或者調整數據的結構,確保在對齊調整后,收/發的數據中每一項的偏移量一致。
3)盡量對發出去的數據都轉換成網絡字節序,接收后轉換回本地字節序,特別是機器字節序不一致時,現有的字節序轉換函數不能滿足所有需求。
4)某些數據類型的表示方式有不同,如浮點數(一般用IEEE 794標准),不能認為正確的傳了一個字節序正確的8字節double型就對了,不同平台對double型的表示方式不同,比如發送1.003,接受沒問題,結果卻得到了其它的數值。

傳結構型數據時對字節序和浮點數的處理,以下的兩點網上的資料不多,詳細記錄一下:
1)目前沒有對8字節或以上數據類型的轉換函數,需要自己實現,網上有很多,下面例舉一個:
uint64_t htonll(uint64_t n) {
return (((uint64_t)htonl(n)) << 32) | htonl(n >> 32);
}
uint64_t ntohll(uint64_t n) {
return (((uint64_t)ntohl(n)) << 32) | ntohl(n >> 32);
}
如果有更長的數據(12字節...),以此類推。

2)對浮點數之類的數據,如果要完全准確,那么用字符串發送。如果直接傳數據,仍要處理字節序,同時確保收發雙方對浮點數的表示方式一致。下面是兩個double型的字節序轉換函數:
double ntoh_double(double net_double) {
uint64_t host_int64;
host_int64 = ntohll(*((uint64_t *) &net_double));
return *((double *) &host_int64);
}

double hton_double(double host_double) {
uint64_t net_int64;
net_int64 = htonll(*((uint64_t *) &host_double));
return *((double *) &net_int64);
}
上述函數之所以沒有對host_double/net_double直接轉成uint64_t時會導致數據截斷。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM