1

我正在尝试使用 C 中的 TCP 套接字编程实现客户端-服务器程序通信。它位于两台安装了 linux OS 的 64 位机器之间。我想在两个进程之间传输一个 c-struct。

为此,我尝试使用一个包 - 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 我收到一个奇怪的数字,可能是内存占用值,(我尝试使用 memset() 填充在从另一端接收数据之前按零排列,在这种情况下,接收到全零的值)

我不明白为什么我没有收到 struct 中数组的正确值。

请注意,我在放入 struct 之前填充数组时尝试使用和不使用 htonl(),另一方面:在从 struct 解码数组时使用和不使用 ntohl()

任何帮助将不胜感激,

4

2 回答 2

3
size_t recv_len = sizeof(buf);
decode_packet(recv_data, recv_len);

这段代码确保将错误的大小传递给decode_packet. 因此,当decode_packet继续检查时recv_len < sizeof(struct packet),该测试毫无意义 -无论接收到多少字节,它都会通过

recv您需要从调用返回的值中获取大小。我最好的猜测是,确实您收到的字节数比您预期的要少。


虽然发送和接收结构非常方便,但它通常是徒劳的。手动序列化数据或使用一些显式机制可能是要走的路。

于 2012-08-07T17:16:52.017 回答
1

您没有向我们展示sendandrecv部分,这更有可能是错误的。我的猜测是您正确地接收了数组中的第一个项目,并且它们在某些时候“变成”垃圾,对吗?

好吧,@cnicutar 是正确的,但让我稍微扩展一下......

首先,当您调用时,send您必须检查返回值并查看是否所有字节都已传输。如果您的结构很大(例如大于底层套接字缓冲区),您将需要多次调用来传输整个结构。与 相同recv不要指望您会在一次recv通话中收到整个消息,不要指望每个人都会收到与相应呼叫recv发送的相同数量的数据。send始终检查已收到多少字节,并recv在必要时再次调用(指向传入缓冲区中的正确位置并减少要接收的字节数)。

所以可能发生了什么,您没有收到足够的数据(也许您甚至没有传输所有数据)并且只有传入缓冲区的开头被填充。因此,结构的其余部分是垃圾或(当您调用时memset)保持零初始化。

还要注意两者sendrecv返回ssize_t而不是size_t可能的负值(表示错误)。

于 2012-08-07T23:07:19.643 回答