2013-01-24 139 views
2

如何用給定的消息規範構造請求消息,然後發送給服務器認爲c socket?客戶端和服務器通信採用二進制協議。以下方法是否正確?用二進制協議發送多字段消息的C socket

給定的消息規格:

 
Field   Fomat Length values 
------------ ------ ------ -------- 
requesID  Uint16 2  20 
requestNum Uint16 2  100 
requestTitle String 10  data sring 
 


    /************** approach 1 ****************/ 
    typedef unsigned short uint16; 
    typedef struct { 
     uint16 requesID [2]; 
     uint16 requestNum [2]; 
     unsigned char requestTitle [10]; 
    }requesMsg; 
    … 
    requesMsg rqMsg; 

    memcpy(rqMsg.requesID, "\x0\x14", 2); //20 
    memcpy(rqMsg.requesNum, "\x0\x64", 2); //100 
    memcpy(rqMsg.requesTitle, "title01 ", 10); 
    … 
    send(sockfd, &rqMsg, sizeof(rqMsg), 0); 

    /************** approach 2 ****************/ 
    unsigned char rqMsg[14]; 
    memset(rqMsg, 0, 14); 
    memcpy(rqMsg, "\x0\x14", 2); 
    memcpy(rqMsg+2, "\x0\x64", 2); 
    memcpy(rqMsg+4, "title01 ", 10); 
    … 
    send(sock, &rqMsg, sizeof(rqMsg), 0); 
+0

只有第二種方法是正確的,你可以自己考慮memset調用的效用。 –

+0

@KerrekSB這並非完全正確。如果他的機器的字節順序與協議的字節順序匹配,並且他使用'pragma pack(1)'作爲結構,他可以得到正確的結果。 (好吧,只要他從字段中刪除數組大小)但不幸的是,代碼是不是真的便攜式然後... – junix

回答

3

恐怕你誤解的東西:長度列似乎要告訴你的字節長度,因此,如果您收到UINT16收到2個字節。

您的第一種方法可能會導致嚴重的問題,通過data structure alignment。如果我在你的鞋子裏,我更喜歡第二種方法,並將自己的字節填入字節數組中。

關於在這裏填充字段的一般注意事項:我不會爲uint16等「native」字段使用memcpy。它可能工作,但僅僅是浪費運行時間。您可以填寫一個結構的字段,只需爲它們分配一個值,如rqMsg.requesID = 20;

另一個問題是您的二進制協議的字節順序或endianness的問題。

作爲一個整體包,我會實現一個「serializeRequest」函數,根據協議將結構的字段轉換爲字節數組。

+0

所有你的回覆對我來說是非常有用的解決這個問題。非常感謝! – GongGong