網路通訊通常分為基於資料結構的和基於流的。http協議就是後者的乙個例子。
有時為了提高程式的處理速度和資料處理的方便,會使用基於資料結構的通訊(不需要對流進行解析)。但是,當需要在多平台間進行通訊時,基於資料結構的通訊,往往要十分注意以下幾個方面:
[1] 位元組序
[2] 變數長度
[3] 記憶體對齊
在常見的系統架構中(linux x86,windows),非單位元組長度的變數型別,都是低位元組在前,而在某些特定系統中,如soalris sparc平台,高位元組在前。如果在傳送資料前不進行處理,那麼由linux x86發向soalris sparc平台的資料值,勢必會有極大的偏差,進而程式執行過程中無法出現預計的正常結果,更嚴重時,會導致段錯誤。
對於此種情況,我們往往使用同一的位元組序。在系統中,有ntoh***(), hton***()等函式,負責將資料在網路位元組序和本地位元組序之間轉換。雖然每種系統的本地位元組序不同,但是對於所有系統來說,網路位元組序是固定的-----高位元組在前。所以,可以以網路位元組序為通訊的標準,傳送前,資料都轉換為網路位元組序。
轉換的過程,也建議使用ntoh***(), hton***()等標準函式,這樣**可以輕鬆地在各平台間進行移植(像通訊這種很少依賴系統api的**,做成通用版本是不錯的選擇)。
變數的長度,在不同的系統之間會有差別,如同是linux2.6.18的平台,在64位系統中,指標的長度為8個位元組,而在32位系統中,指標又是4個位元組的長度---此處只是舉個例子,很少有人會將指標作為資料傳送出去。下面是我整理的在64位linux系統和32位linux系統中,幾種常見c語言變數的長度:
short int long long long ptr time_t
32位 2 4 4 8 4 4
64位 2 4 8 8 8 8
在定義通訊用的結構體時,應該考慮使用定常的資料型別,如uint32_t,4位元組的固定長度,並且這屬於標準c庫(c99),在各系統中都可使用。
記憶體對齊的問題,也與系統是64位還是32位有關。如果你手頭有32位和64位系統,不妨寫個簡單的程式測試一下,你就會看到同乙個結構體,即便使用了定常的資料型別,在不同系統中的大小是不同的。對齊往往是以4位元組或8位元組為準的,只要你寫的測試程式,變數所佔空間沒有對齊到4或8的倍數即可,舉個簡單的測試用的結構體的例子吧:
struct student
;在每個系統上看下這個結構體的長度吧。
記憶體對齊,往往是由編譯器來做的,如果你使用的是gcc,可以在定義變數時,新增__attribute__,來決定是否使用記憶體對齊,或是記憶體對齊到幾個位元組,以上面的結構體為例:
1)到4位元組,同樣可指定對齊到8位元組。
struct student
__attribute__ ((aligned(4)));
2)不對齊,結構體的長度,就是各個變數長度的和
struct student
__attribute__ ((packed));
希望這些內容能對你有所幫助。
跨平台時基於資料結構的網路通訊
網路通訊通常分為基於資料結構的和基於流的。http協議就是後者的乙個例子。有時為了提高程式的處理速度和資料處理的方便,會使用基於資料結構的通訊 不需要對流進行解析 但是,當需要在多平台間進行通訊時,基於資料結構的通訊,往往要十分注意以下幾個方面 1 位元組序 2 變數長度 3 記憶體對齊 在常見的系...
基於UDP的網路通訊程式
我們知道tcp ip協議是至今發展最為成功的協議之一,也是整個網際網路的基礎。它在傳輸層有兩個不同的協議 tcp和udp,用途都很廣泛,下面我就udp做乙個示例程式。整個例子有兩個程式組成,乙個傳送資料,另乙個程式接收資料後,完成繪圖工作。本文程式執行效果圖如下 一 傳送程式 首先建立資料傳送程式 ...
網路通訊時整型資料與位元組之間的轉換
在進行socket通訊時,常常需要傳輸某個變數值的長度,比如乙個註冊包有名字,位址等資訊。在進行包的封裝定義時,一般是以namelength name addresslength address形式封裝。而無線網路傳輸是按位元組流傳輸的,這就要求對整形資料進行轉換。乙個位元組表示的整數最大範圍是2的...