C - структура Marshaling / Unmarshaling с htonl и ntohl - PullRequest
0 голосов
/ 01 марта 2019

Итак, у меня есть структура в c, и мне нужно отправить ее через сокет UDP.RPCmessage должно быть сведено в байтовый массив, который является message.data.Затем message.data отправляется через сокет UDP.

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 голосов
/ 01 марта 2019

Функция htonl возвращает значение типа uint32_t.Это не указатель, поэтому не имеет смысла приводить его к одному.Вот что говорит вам предупреждение.

Вам нужно сохранить результат во временной переменной, а затем передать адрес временной переменной в 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);

Кстати,слава за правильное маршалинг / демаршалинг вашей структуры данных вместо попытки взять адрес структуры для отправки / получения.

...