2013-01-24 101 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