C에서 char []를 내 구조물에 복사하는 방법
문제
UDP 소켓 위로 구조물을 보내려고합니다.
구조물 패킷 {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, 바이트); 오류가 발생합니다.
오류 : 포인터 유형으로 변환 할 수 없습니다
내가 뭘 잘못하고 있죠? 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 *) ¤tpkt, bytes, 0,
(struct sockaddr *) &client, &clientSize);
C에서는 우리가 그것을 숯으로 던져 바이트를 보낼 수 있다는 것이 좋습니다.
해결책
currentpkt
구조물 유형입니다. 이 작업을 수행하려면 구조물에 대한 포인터를 가져와야합니다.
memcpy(¤tpkt, recv, bytes);
두 번째 질문에는 다른 문제가 있습니다. 패킷에서 더 많은 바이트를 받으면 어떻게해야합니까? sizeof(struct Packet)
? 지금 쓰여진 것처럼 구조물을 오버런합니다.
클라이언트 및 서버 애플리케이션이 다른 컴파일러 또는 설정을 사용하여 컴파일되는 경우 또는 다른 엔지니어가 다른 플랫폼에서 어떻게됩니까? 이 경우 구조물은 두 플랫폼에서 크기가 다를 수 있으며 메모리에 다르게 배치 될 수 있습니다.
다른 팁
그래서 나는 그렇게 생각하고 있습니다 currentpkt
a struct Packet
, 그리고 당신은 정말로 말하려고했습니다 ¤tpkt
.
나는 또한 그것을 주목할 수도 있습니다 memcpy()
이미 가지고 있습니다 void *
매개 변수 (void *)
캐스트는 필요하지 않습니다.
memcpy((void *) currentpkt, (void *) recv, bytes);
오류 메시지는 캐스트 문제를 나타냅니다. recv
a이기 때문에 괜찮습니다 char[]
((void*)로 변환하는 데 문제가 없습니다). 문제는 그게되어야합니다 currentpkt
포인터 유형이되어서는 안됩니다.
그것은 당신의 스 니펫에 선언되지 않았으므로 그것이 무엇인지 모르지만 거기서 시작할 것입니다.
전체 구조물에서 memcpy를하는 것은 정말로 악합니다 :-). 우선 모든 데이터가 아키텍처에 따라 다르게 정렬 될 수 있습니다. 아키텍처가 다른 쪽에서 다른 경우 어떻게해야합니까? 또한 __packed와 같은 키워드를 사용하는 것은 다른 컴파일러간에 휴대 할 수 없습니다.
내가 아는 바와 같이, 가장 좋은 것은 PHP 팩/포장과 같은 API를 사용하는 것입니다. 이로 인해 __packed와 같은 컴파일러 특정 Ugly 키워드를 사용하지 않고 코드를 진정으로 휴대 할 수 있습니다.
나는 그물에서 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);
휴대용 코드를 생성 할뿐만 아니라 아름답습니다.)