天天看點

網絡資料(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時會導緻資料截斷。

繼續閱讀