1. 程式人生 > >TCP程式設計之一 傳輸struct型別資料條件

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

在網路通訊過程中往往涉及一些有關聯的引數傳遞,例如結構體之類的。對於結構體其實方法挺簡單,由於結構體物件在記憶體中分配的空間都是連續的,所以可以將整個結構體直接轉化成字串傳送,到了接收方再將這個字串還原成結構體就可以了。

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

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

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

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

1、結構體資料全部都是陣列

  1. typedefstruct _tag_user_info_  
  2. {  
  3.     char cUserID[20];  
  4.     char cUserSex[10];  
  5.     char cUserName[18];  
  6.     char cUserNativePlace[50];  
  7. } UserData;  
  8.   //傳送方:建立一個物件並初始化各個引數,然後傳送。
  9. UserData sendUser;  
  10. memcpy ( sendUser.cUserID, "412902198312120311",sizeof("412902198312120311"));  
  11. memcpy ( sendUser.cUserSex, "male",sizeof("male"));  
  12. memcpy ( sendUser.cUserName, "JianYa.Lee",sizeof("JianYa.Lee"));  
  13. memcpy (  
  14. sendUser.cUserNativePlace,  
  15. "Asia. P.R.C .HeNan-DengZhouShi",  
  16. sizeof("Asia. P.R.C.HeNan-DengZhouShi"
    )  
  17. );  
  18. send ( m_oSendSocket, (char*)&sendUser,sizeof(UserData), 0 );  

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

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

  1. // 定義的char陣列足夠大
  2. charcRcvBuffer[1024]  = {0};  
  3. // 定義一個UserData物件, 用於容納轉換資訊
  4. UserData recvUser;  
  5. recv( m_RcvSocket, cRcvBuffer, sizeof(cRcvBuffer),0 );  
  6. // 強轉, 請注意sizeof的內容
  7. memcpy( &recvUser, cRcvBuffer, sizeof(UserData) );  

這樣得到的recvUser物件裡的資料與sendUser相同了。

2、結構體資料沒有包含陣列

  1. // 傳送方:建立struct結構體
  2. typedefstruct _tag_other_data_  
  3. {  
  4.        INT32  nValue;  
  5.     char  cValue;  
  6.     bool  blValue;  
  7.     float  fValue;  
  8.     double  dValue;  
  9.     short  sValue;  
  10. } SecondData;  
  11. // 定義結構體物件,並初始化
  12. SecondData oScdData;  
  13. // 初始化資料內容
  14. oScdData.blValue = true;  
  15. oScdData.cValue = 'h';  
  16. oScdData.dValue = 0.1234567;  
  17. oScdData.fValue  =3.14159f;  
  18. oScdData.nValue = 123456;  
  19. oScdData.sValue = 0x1024;  
  20. // 注意sizeof內容
  21. send(m_oSendSocket, (char*)&oScdData,sizeof(SecondData), 0);  
  22. 接收方:首先定義SecondData結構體,資料型別、宣告次序需完全一樣;其次宣告一個足夠大的char型別陣列;最後強轉。  
  23. // 定義char型別陣列
  24. charcRcvBuffer[1024] = {0};  
  25. SecondData oRcvData;  
  26. // 注意sizeof內容
  27. recv(m_oRcvSocket, cRcvBuffer, sizeof(cRcvBuffer), 0);  
  28. // 強制轉換, 注意sizeof內容
  29. memcpy(&oRcvData, cRcvBuffer, sizeof(SecondData));  


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

  1. // 定義char型別陣列
  2. charcRcvBuffer[1024] = {0};  
  3. SecondData oRcvData;  
  4. // 注意sizeof內容
  5. recv(m_oRcvSocket, cRcvBuffer, sizeof(cRcvBuffer), 0);  
  6. // 強制轉換, 注意sizeof內容
  7. memcpy(&oRcvData, cRcvBuffer, sizeof(SecondData));  

3、多個結構體資料的傳接

傳送方:

  1. struct structA  
  2. {  
  3.     INT32 nValue;  
  4.     char    cValue;  
  5. };  
  6. struct structB  
  7. {  
  8.     bool  blValue;  
  9.     short  sValue;  
  10. };  
  11. struct structC  
  12. {  
  13.     float fValue;  
  14.     char  cValue;  
  15.     unsigned  long  unValue;  
  16. };  
  17.    //  三個結構體定義各不相同,現在要給它們建立一個統一的傳接模式,此時可以考慮使用聯合union,外加一個型別指示。
  18. typedefstruct _tag_unification_data_  
  19. {  
  20. // 用於指示結構體型別, 比如IS_STRUCT_A就代表structA、
  21. // IS_STRUCT_B就代表struct_B、
  22.     // IS_STRUCT_C就代表structC
  23.     INT32  nStructType;  
  24.     // 每次傳送的是三種struct中的一種
  25.     union
  26.     {  
  27.         struct structA aData;  
  28.         struct structB bData;  
  29.         struct structC cData;  
  30.     };  
  31. }  PACKETDATA;  
  32. // 結構體型別標識
  33.     enum{IS_STRUCT_A, IS_STRUCT_B, IS_STRUCT_C};  
  34. // 定義結構體物件,並初始化
  35.     PACKETDATA oMyData;  
  36.     // 傳送structA型別資料
  37.     oMyData.nStructType  = IS_STRUCT_A;  
  38.     oMyData.aData.cValue = 'g';  
  39.     oMyData.aData.nValue = 130;  
  40.     // 注意後面的sizeof內容
  41. send(oSendSocket, (char*)&oMyData,sizeof(PACKETDATA), 0);  

接收方:

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

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

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

  1. // 定義char型別陣列
  2. charcRcvBuffer[1024] = {0};  
  3. PACKETDATA oRcvData;  
  4. // 注意sizeof內容
  5. recv(m_oRcvSocket, cRcvBuffer, sizeof(cRcvBuffer), 0);  
  6. // 強制轉換, 注意sizeof內容
  7. memcpy(&oRcvData, cRcvBuffer, sizeof(PACKETDATA));  
  8. // 在使用時進行具體型別判斷
  9. switch (oRcvData.nStructType)  
  10.    {  
  11. caseIS_STRUCT_A:  
  12. 相關推薦

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

    在網路通訊過程中往往涉及一些有關聯的引數傳遞,例如結構體之類的。對於結構體其實方法挺簡單,由於結構體物件在記憶體中分配的空間都是連續的,所以可以將整個結構體直接轉化成字串傳送,到了接收方再將這個字串還原成結構體就可以了。網路傳輸struct資料的約束有兩個:約束一、就是結構體

    linux多執行緒程式設計之一多執行緒資料同步及相關api使用示例

    多執行緒的使用在編碼過程中非常常見,如果快速的理解和掌握linux下的多執行緒程式設計呢?下文即將為您揭曉。一.linux多執行緒基本的建立及相關API使用: 1.執行緒的建立: int pthread_create(pthread_t thread, const pthread_attr_t attr,

    【Java TCP/IP Socket程式設計】----傳送和接收資料----構建和解析協議訊息

    --------筆記來自於書籍《Java TCP/IP Socket程式設計》。 簡介 使用套接字時,通常要麼是需要同時建立通訊通道兩端的程式,要麼實現一個給定的協議進行通訊。如果知道通訊雙方都使用java實現,且擁有對協議的完全控制權,那麼就可以使用Java的內建工具如Serialiabl

    【Java TCP/IP Socket程式設計】----傳送和接收資料----訊息成幀與解析

    目錄   簡介 成幀與解析 成幀技術案例 簡介 在程式中使用套接字向其他程式提供資訊或者使用其他程式提供的資訊,這就需要任何需要交換資訊的程式間在資訊編碼方式上達成共識(包含了資訊交換的形式和意義),稱為協議,用來實現特定的應用程式的協議叫應用程式協議。大部分應

    Day 1 變數,基礎資料型別條件語句

    1.變數 變數的含義:把程式執行過程中產生的值儲存起來。 方便後面的程式呼叫 變數的命名規範   1.由數字,字母,下劃線組成   2.不能以數字開頭   3.不能使用Python的關鍵字 建議:變數名不要太長,要有意義並且區分大小寫,同時不要使用中文 推薦:使用駝峰體: 每個單詞的首字母大寫

    Python基礎學習---資料型別條件語句(三)

    1 #!/usr/bin/python3 list = ['Google', 'Runoob', 1997, 2000] print ("原始列表 : ", list) del list[2] print ("刪除第三個元素 : ", list) 2 #!/usr/bi

    程式設計第八課:基本資料型別

    在我們玩遊戲的時候,遊戲中的角色是有型別的,有敏捷型、力量型、法術型等等。同樣C語言中的資料也是有型別的,C語言中,資料型別可分為:**基本資料型別,構造資料型別,指標型別,空型別四大類。**所示: 這裡我們先給大家講解基本資料型別中最簡單也是最常用的整型、實

    C++11多執行緒程式設計 第四章: 共享資料和競態條件

    C++11 Multithreading – Part 4: Data Sharing and Race Conditions Varun February 21, 2015C++11 Multithreading – Part 4: Data Sharing and Race Con

    學習筆記:QT網路程式設計:C2S基於TCP的檔案傳輸

    預處理: 1在.pro加入一條語句 QT += network 記得儲存檔案 2.標頭檔案中可包含標頭檔案/儘量用前向宣告(因為只宣告不用) TCP檔案傳輸

    Java TCP/IP Socket——深入剖析socket—資料傳輸的底層實現

    本文轉自:http://blog.csdn.net/ns_code/article/details/15813809 底層資料結構 如果不理解套接字的具體實現所關聯的資料結構和底層協議的工作細節,就很難抓住網路程式設計的精妙之處,對於TCP套接字來說,更是如此。套接

    python程式設計基礎2:python資料型別

    從一個簡單的例子開始:輸入5個數,按從大到小輸出。你怎麼做? 其實可以按照昨天的一個例題那樣子做,但是資料較多,繁瑣且容易出錯。但是使用python的列表(list)資料型別就不會這樣了。 1、列表 先通過如下的例子瞭解list的一些基本的操作: >>>

    mysql 資料型別 約束條件

    今日內容: 引擎:決定資料庫存取資料的方式==>不同的特點==>不同的使用者體驗 資料型別:規定了資料庫可以存放哪些資料 約束:限制儲存資料的規則   引擎: 針對於表的 前提:引擎是建表時規定,提供給表使用,不是資料庫 mysql>> show engines

    計算機網路(5)-傳輸層--TCP傳輸:可靠資料傳輸、流量控制、3次握手過程

    TCP傳輸 TCP連線提供的服務是全雙工服務,同一連線能夠雙向傳輸資料,同時,也是點對點的連線(僅有一個傳送方和一個接收方)。 TCP報文段結構 TCP報文段由首部欄位和資料欄位組成。 首部欄位 源埠號和目的埠號:用於多路分用和多路複用 因特網檢驗和:差

    axis2系列之傳輸複雜型別資料

    public static void main(String[] args) { RPCServiceClient client = null; try { client = new RPCServiceClient(); Options options = client.getOptio

    HTTP詳解(五):HTTP POST方法傳輸多種型別資料

    上圖中主要就是上傳excel時的請求頭,我們重點看一下Content-Type,可以看出Content-Type=multipart/form-data; boundary=---------------------------3618134789,其中將Content_Type設定成multipart/fo

    Java的時間型別資料使用Json字串傳輸時變成一串數字的解決方法

    終於有時間來寫一下這幾天的收穫了,這幾天一直在幫一個研究生完成他的畢業設計,他的畢業設計主要是做一個灌溉系統,該專案使用SSM框架開發,但我還沒有系統學習框架,之前對於一個需求都是嚴格按照MVC設計模式,不採用框架來搭建系統,使用的都是單純的Servlet程式處理請求,並沒

    C#程式設計向SQLite資料庫中正確寫入DateTime型別資料

    最近用C#編寫了一個程式,裡面涉及向SQLite資料庫寫入DateTime型別資料,實際時間為2012/11/30 0:20:00,但寫入資料庫後變成1899/12/30 00:00:00。 實際情況是時間寫入資料庫失敗,1899/12/30 00:00:00是資料

    時間型別資料使用between ...and ..語句條件查詢時應注意的問題

    大多數專案中,我們使用的時間精度都是到多少號,在未經過處理時,儲存在資料庫後,時間精度就到毫秒了。比如輸入‘2013-12-30’,但儲存在資料庫中就變成‘2013-12-30 00:00:00.000’ 。平時使用 between ..and..語句時,對於數值型別的資料

    C語言程式設計---9:自定義資料型別

    /*輸入學生的學號、姓名、性別、年齡、成績、家庭住址,輸出成績較高的學生資訊*/ #include<stdio.h> void main() { struct student

    我所不知道的TCP Socket程式設計(五)-交換資料、套接字讀寫操作

    五:交換資料 已經建立了伺服器和客戶端的連結,現在需要讓它們進行資料交換;      你可以將TCP連線想象成一串連線了本地套接字和遠端套接字的管子,我們可以沿著這個管子傳送和接受資料;