TCP程式設計之一 傳輸struct型別資料條件

2021-08-19 15:00:33 字數 4117 閱讀 4948

網路傳輸struct資料的約束有兩個:

約束一、就是結構體的大小必須是固定的,不能含有可變大小資料,例如cstring、string之類的資料。換句話說,結構體所包含的資料必須是c++基本型別資料以及這些基本型別資料所形成固定大小的陣列。

約束二、就是傳接兩方結構體定義必須一模一樣,包括資料宣告次序。如果要傳送的結構體包含「#pragma pack (n)」,則接收方在定義此結構體時也要使用「#pragma pack (n)」宣告。傳接之所以能夠成功是因為結構體資料的記憶體區域連續性所保證的

本來嘛在c/c++中所有資料究其本質都是位元組型別,只是在表現時各自不同罷了,所以只要能找到合適的轉換為位元組型別資料的途徑就ok了。而位元組型別和char型別一樣都是乙個位元組長度,所以問題又等同於找一條合適途徑,將資訊轉換為固定長度char陣列型別。

[cpp] 

view plain

copy

typedef

struct

_tag_user_info_  

userdata;  

//傳送方:建立乙個物件並初始化各個引數,然後傳送。

userdata senduser;  

memcpy ( senduser.cuserid, "412902198312120311"

,sizeof

("412902198312120311"

));  

memcpy ( senduser.cuser***, "male"

,sizeof

("male"

));  

memcpy ( senduser.cusername, "jianya.lee"

,sizeof

("jianya.lee"

));  

memcpy (  

senduser.cusernativeplace,  

"asia. p.r.c .henan-dengzhoushi"

,  sizeof

("asia. p.r.c.henan-dengzhoushi"

)  );  

send ( m_osendsocket, (char

*)&senduser,

sizeof

(userdata), 0 );  

需要注意的地方:send函式的第三個引數,也就是傳送資料長度必需是結構體的大小,這樣傳送方就已經將這個senduser物件以字串的形式傳送出去了,剩下的工作就由接收方來完成了

接收方:首先也必須有userdata這個結構體型別定義。其次,首先定義乙個充分大char型別陣列,用於接收網路傳送資料。然後將接收到的資料用memcpy函式完成強轉即可。

[cpp] 

view plain

copy

// 定義的char陣列足夠大

charcrcvbuffer[1024]  = ;  

// 定義乙個userdata物件, 用於容納轉換資訊

userdata recvuser;  

recv( m_rcvsocket, crcvbuffer, sizeof

(crcvbuffer),0 );  

// 強轉, 請注意sizeof的內容

memcpy( &recvuser, crcvbuffer, sizeof

(userdata) );  

這樣得到的recvuser物件裡的資料與senduser相同了。

[cpp] 

view plain

copy

// 傳送方:建立struct結構體

typedef

struct

_tag_other_data_  

seconddata;  

// 定義結構體物件,並初始化

seconddata oscddata;  

// 初始化資料內容

oscddata.blvalue = true

;  oscddata.cvalue = 'h'

;  oscddata.dvalue = 0.1234567;  

oscddata.fvalue  =3.14159f;  

oscddata.nvalue = 123456;  

oscddata.svalue = 0x1024;  

// 注意sizeof內容

send(m_osendsocket, (char

*)&oscddata,

sizeof

(seconddata), 0);  

接收方:首先定義seconddata結構體,資料型別、宣告次序需完全一樣;其次宣告乙個足夠大的char

型別陣列;最後強轉。  

// 定義char型別陣列

charcrcvbuffer[1024] = ;  

seconddata orcvdata;  

// 注意sizeof內容

recv(m_orcvsocket, crcvbuffer, sizeof

(crcvbuffer), 0);  

// 強制轉換, 注意sizeof內容

memcpy(&orcvdata, crcvbuffer, sizeof

(seconddata));  

接收方:首先定義seconddata結構體,資料型別、宣告次序需完全一樣;其次宣告乙個足夠大的char型別陣列;最後強轉。

[cpp] 

view plain

copy

// 定義char型別陣列

charcrcvbuffer[1024] = ;  

seconddata orcvdata;  

// 注意sizeof內容

recv(m_orcvsocket, crcvbuffer, sizeof

(crcvbuffer), 0);  

// 強制轉換, 注意sizeof內容

memcpy(&orcvdata, crcvbuffer, sizeof

(seconddata));  

傳送方:

[cpp] 

view plain

copy

struct

structa  

;  struct

structb  

;  struct

structc  

;  //  三個結構體定義各不相同,現在要給它們建立乙個統一的傳接模式,此時可以考慮使用聯合union,外加乙個型別指示。

typedef

struct

_tag_unification_data_  

;  }  packetdata;  

// 結構體型別標識

enum

;  // 定義結構體物件,並初始化

packetdata omydata;  

// 傳送structa型別資料

omydata.nstructtype  = is_struct_a;  

omydata.adata.cvalue = 'g'

;  omydata.adata.nvalue = 130;  

// 注意後面的sizeof內容

send(osendsocket, (char

*)&omydata,

sizeof

(packetdata), 0);  

接收方:

首先必需由packetdata一樣的定義;

其次,定義乙個足夠大的char陣列;

最後完成強轉,在使用的時候進行具體型別判斷即可。

[cpp] 

view plain

copy

// 定義char型別陣列

charcrcvbuffer[1024] = ;  

packetdata orcvdata;  

// 注意sizeof內容

recv(m_orcvsocket, crcvbuffer, sizeof

(crcvbuffer), 0);  

// 強制轉換, 注意sizeof內容

memcpy(&orcvdata, crcvbuffer, sizeof

(packetdata));  

// 在使用時進行具體型別判斷

switch

(orcvdata.nstructtype)  

c DLL程式設計之一

dll的優點 簡單的說,dll有以下幾個優點 1 節省記憶體。同乙個軟體模組,若是以源 的形式重用,則會被編譯到不同的可執行程式中,同時執行這些exe時這些模組的二進位製碼會被重複載入到記憶體中。如果使用dll,則只在記憶體中載入一次,所有使用該dll的程序會共享此塊記憶體 當然,像dll中的全域性...

RAPI程式設計之一

今天剛開始學習rapi程式設計,先將今天學習的成果放出來,大家學習。如果 有問題,請提出,多謝 在pc上使用vc6,好久沒有用它了。一直在evc4下程式設計,呵呵.rapi功能的實現,需要rapi.dll和rapi.h。在以下的實現中,link的動態庫是c windows system32 rapi...

傳輸層 傳輸控制協議TCP概述 之一

一,tcp的主要特點 1 面向連線 2 點對點 3 可靠交付,無差錯 不丟包 不重複 按需到達 4 全雙工通訊,接收端和傳送端都設有傳送快取和接受快取 5 面向位元組流 tcp把應用程式交付下來的資料僅僅看成 一連串無結構位元組流 但tcp不知道位元組流含義。tcp也不保證接收方收到的資料塊和傳送方...