Как скопировать char [] в c в мою структуру - PullRequest
0 голосов
/ 07 декабря 2009

Я пытаюсь отправить свою структуру через сокет UDP.

struct Packet { int seqnum; данные char [BUFFERSIZE]; };

Так что на отправителя у меня

bytes = sizeof(packet);
char sending[bytes];
bzero(sending, bytes);
memcpy((void *) sending, (void *) &packet, sizeof(bytes));
bytes = sendto(sockfd, sending, sizeof(sending), 0,
    (struct sockaddr *) &client, clientSize);

Так что я надеюсь, что копирует мою структуру в Char [].

На ресивере у меня

int bytes;
bytes = sizeof(struct Packet);
char recv[bytes];
bytes = recvfrom(sockfd, recv, bytes, 0,
    (struct sockaddr *) &client, &clientSize);
memcpy((void *) currentpkt, (void *) recv, bytes);

Однако на приемнике с memcpy ((void *) currentpkt, (void *) recv, bytes); Я получаю ошибку:

ошибка: невозможно преобразовать в тип указателя

Что я делаю не так? Есть ли лучший способ отправить мою структуру через сокет UDP?

***** ОБНОВЛЕНИЕ *****

Спасибо всем за ответы. В конце я пропустил '&', но мой код теперь выглядит следующим образом.

Отправитель:

void udt_send(struct Packet packet) {
    int bytes;
    bytes = sendto(sockfd, (char *) &packet, sizeof(packet), 0,
            (struct sockaddr *) &client, clientSize);
}

Получатель:

bytes = recvfrom(sockfd, (char *) &currentpkt, bytes, 0,
        (struct sockaddr *) &client, &clientSize);

В Си приятно, что мы можем просто привести его к символу и отправить байты.

Ответы [ 4 ]

3 голосов
/ 07 декабря 2009

currentpkt имеет структурный тип; вам нужно получить указатель на структуру, чтобы заставить это работать:

memcpy(&currentpkt, recv, bytes);

По второму вопросу у вас есть другие проблемы. Что если вы получите больше байтов в пакете, чем sizeof(struct Packet)? Как написано сейчас, вы переполните свою структуру.

Что если клиентские и серверные приложения компилируются с использованием разных компиляторов или настроек или на платформах с разным порядком байтов? В этом случае структура может иметь разные размеры на двух платформах и может быть размечена в памяти по-разному.

1 голос
/ 07 декабря 2009

Так что я думаю, что currentpkt - это struct Packet, и что вы действительно хотели сказать &currentpkt.

Могу также заметить, что memcpy() уже имеет параметры void *, поэтому приведения (void *) не нужны.

0 голосов
/ 07 декабря 2009

Создание memcpy из всей структуры - это действительно зло :-). Прежде всего, данные могут быть выровнены по-разному в зависимости от архитектуры. Что, если архитектура отличается с другой стороны? Также использование таких ключевых слов, как __packed, не переносимо между различными компиляторами.

Лучшее, насколько я знаю, это использовать такой API, как PHP pack / unpack. Это делает код действительно переносимым без использования специфических для компилятора уродливых ключевых слов, таких как __packed.

Я не нашел в сети ни одного пакета / распаковки для C, поэтому я написал свой собственный.

Например, чтобы распаковать два слова из двоичных данных:

   pbuf_unpack(p_bts, "ww", &hdr, &ver); 

Где

   p_bts is binary data
   "ww" describes the data structure
   hdr and ver is where to put the datause an API like the PHP pack/unpack. 

Еще один более обширный пример:

   pbuf_unpack(p_entry, "bbbbbbbbww",
      &atrb_mbr.def_boot_par, &atrb_mbr.head_start, &atrb_mbr.sec_start,
      &atrb_mbr.cyl_start, &atrb_mbr.type, &atrb_mbr.head_end, 
      &atrb_mbr.sec_end, &atrb_mbr.cyl_end, &atrb_mbr.start_sec_pbr,
      &atrb_mbr.sec_per_par);

Упаковка очень проста:

   pbuf_pack(boot_buf, "sdsdhbhbhhbhhhwwbbbwsdsd", sizeof(fat_jmp_boot_t), 
      boot.jmp, sizeof(fat_oem_nm_t), boot.oem_nm, boot.n_bps, boot.n_spc, 
      boot.n_rs, boot.n_fs, boot.n_rde, boot.n_ts16, boot.media_des, 
      boot.n_fatsz16, boot.n_spt, boot.n_hds, boot.n_hs, boot.n_ts32, 
      boot.drv_no, boot.rsrvd1, boot.boot_sig, boot.vol_id, 
      sizeof(fat_vol_lbl_t), boot.lbl, sizeof(fat_vol_type_t), boot.type);

Он не только создает переносимый код, но и красив;)

0 голосов
/ 07 декабря 2009

memcpy((void *) currentpkt, (void *) recv, bytes);

Ваше сообщение об ошибке указывает на проблему приведения. recv в порядке, так как это char[] (нет проблем с преобразованием в (void *)). Проблема должна заключаться в том, что currentpkt не должен быть указателем типа.

Это не объявлено в вашем фрагменте, поэтому я не знаю, что это, но я бы начал с этого.

...