我正在尝试使用C语言中的TCP套接字编程实现客户端 - 服务器程序通信。 它位于安装了Linux操作系统的两台64位机器之间。 我想在两个进程之间传递一个c-struct。
为此,我尝试使用pack - unpack()函数。
请考虑以下代码段
/*---------------------------------------------------------
on the sending side I have:
---------------------------------------------------------*/
struct packet {
int64_t x;
int64_t y;
int64_t q[maxSize];
} __attribute__((packed));
int main(void)
{
// build packet
struct packet pkt;
pkt.x = htonl(324);
pkt.y = htonl(654);
int i;
for(i = 0; i< maxSize; i++){
pkt.q[i] = i; **// I also try pkt.q[i] = htonl(i);**
}
// and then do the send
}
/*-----------------------------------------------------------------------------
in the receiving side:
-----------------------------------------------------------------------------*/
struct packet {
int64_t x;
int64_t y;
int64_t q[maxSize];
} __attribute__((packed));
static void decodePacket (uint8_t *recv_data, size_t recv_len)
{
// checking size
if (recv_len < sizeof(struct packet)) {
fprintf(stderr, "received too little!");
return;
}
struct packet *recv_packet = (struct packet *)recv_data;
int64_t x = ntohl(recv_packet->x);
int64_t y = ntohl(recv_packet->y);
int i;
printf("Decoded: x=%"PRIu8" y=%"PRIu32"\n", x, y);
for(i=0;i<maxSize;i++){
**//int64_t res = ntohl(recv_packet->q[i]); I also try to print res**
printf("%"PRIu32"\n" , recv_packet->q[i]);
}
}
int main(int argc, char *argv[]){
// receive the data and try to call decodePacket()
int8_t *recv_data = (int8_t *)&buf; //buf is the data received
size_t recv_len = sizeof(buf);
**decode_packet(recv_data, recv_len);**
}
//-----------------------------------------------------------------------------
现在的问题是我正在结构中正确地接收x和y的值, 但是对于结构中的数组q我收到一个奇怪的数字,可能是一个内存grabage值,(我尝试使用memset()在从另一端接收数据之前用零填充数组,在这种情况下全部为零的值已收到)
我不明白为什么我没有在struct中收到数组的正确值。
请注意在填充数组之前我尝试使用和不使用htonl(),然后放入struct, 另一方面:在从struct
解码数组时使用和不使用ntohl()任何帮助将不胜感激,
答案 0 :(得分:3)
size_t recv_len = sizeof(buf); decode_packet(recv_data, recv_len);
这段代码确保将错误的大小传递给decode_packet
。因此,当decode_packet
继续检查recv_len < sizeof(struct packet)
时,该测试毫无意义 - 无论收到多少字节,它都将始终通过。
您需要从recv
调用返回的值中获取大小。我最好的猜测是,你收到的字节数确实少于预期。
虽然发送和接收结构非常方便,但它通常是徒劳的。手动序列化数据或使用一些显式机制可能是要走的路。
答案 1 :(得分:1)
您没有向我们展示send
和recv
部分,这更有可能是错误的。我的猜测是你正确接收到数组中的第一项,并且它们在某些时候“变成”垃圾,是不是?
嗯,@ cnicutar是正确的,但让我稍微扩展一下......
首先,当你调用send
时,你必须检查返回值并查看是否所有字节都已传输。如果您的结构很大(例如,大于底层套接字缓冲区),则需要多次调用来传输整个结构。与recv
相同,不希望您在一次recv
来电中收到整封邮件,不要指望每个recv
都会收到相同数量的相应的send
电话发送的数据。始终检查已接收的字节数,并在必要时再次调用recv
(指向传入缓冲区中的正确位置并减少要接收的字节数)。
所以可能发生了什么,你没有收到足够的数据(也许你甚至没有传输所有数据),只有你的传入缓冲区的开头才被填满。因此,结构的其余部分是垃圾或(当您调用memset
时)保持初始化为零。
另请注意,send
和recv
返回ssize_t
而不是size_t
,因为可能出现负值(表示错误)。