C-使用htonl和ntohl编组/解组结构

时间:2019-03-01 18:13:09

标签: c struct marshalling unmarshalling memcpy

所以我在c中有一个结构,我需要通过UDP套接字发送它。 RPCmessage应该被展平为一个字节数组,即message.data。然后通过UDP套接字发送message.data。

typedef struct {
    enum {Request, Reply} messageType; /* same size as an unsigned int */
    unsigned int RPCId; /* unique identifier */
    unsigned int procedureId; /* e.g.(1,2,3,4) for (+, -, *, /) */
    int arg1; /* argument/return parameter */
    int arg2; /* argument/return parameter */
    /* each int (and unsigned int)is 4
    bytes */
} RPCmessage;

typedef struct {
    unsigned int length;
    unsigned char data[SIZE];
} Message;

我对c不熟练,因此我不确定如何将其展平为字节数组以通过套接字发送。我相信我需要使用htonl()进行编组,并使用ntohl()进行编组。但是我无法让我的memcpy表现出我需要的方式。目前,我收到警告:从大小不同的整数转换为指针[-Wint-to-pointer-cast]

void marshal(RPCmessage *rm, Message *message){
    memcpy(&message->data[0], (char *)htonl(rm->messageType), sizeof(rm->messageType));
    memcpy(&message->data[4], (char  *)htonl(rm->RPCId), sizeof(rm->RPCId));

    /* more marshaling follows for the other 4 members */
}

希望它简单吗?但是,当解决了该问题后,我确定将字节数组解组回RPCmessage结构中将会遇到问题。我的猜测是要执行类似的操作……但是我不知道如何使用ntohl将其恢复为主机顺序。

void unMarshal(RPCmessage *rm, Message *message){
    //here, I am assuming *message is the message received from the socket
    memcpy(rm->messageType, message->data[0], sizeof(rm->messageType));
    memcpy(rm->RPCId, message->data[4], sizeof(rm->RPCId));

    /*more unmarshaling...*/

}

我一直在阅读手册页,但没有点击。指针目前在我头上有点过头,试图更好地理解它们。 预先感谢您救了我一命。

1 个答案:

答案 0 :(得分:2)

htonl函数返回类型为uint32_t的值。它不是指针,因此将其强制转换为一个指针没有任何意义。这就是警告告诉你的。

您需要将结果存储在temp变量中,然后将temp的地址传递给memcpy

uint32_t msgType = htonl(rm->messageType);
uint32_t rpcId = htonl(rm->RPCId);
memcpy(&message->data[0], &msgType, sizeof msgType);
memcpy(&message->data[4], &rpcId, sizeof rpcId);

顺便说一句,对您的数据结构执行适当的封送处理/取消封送处理,而不是尝试获取该结构的地址来发送/接收它,这是一种荣誉。