如何通过 UDP 发送结构并在另一端接收?

How to send a struct over UDP and receive on the other side?

我有一个关于套接字编程的非常具体的问题。我的代码类似于下面。

struct data_packet{
   unsigned char seqnumber; 
   char data[500]; 
}

struct data_packet packettosend; 
packettosend.seqnumber = '0'
packettosend.data = 'some binary data' (this could be any length from 0 bytes to 500 bytes) 

//sender code 
char buffer[501]; 
memcpy(buffer, &packettosend, sizeof(packetosend)); 
int s = sendto(socketfd, buffer, sizeof(buffer), 0 , .......other params); 

//receiver code
char recvbuffer[501];
int t = recvfrom(recvsocketdf, recvbuffer, 501, 0 ....other params);
  
How do I set up my receiver to receive the data and save it on a `struct data_packet`?    

seqnumber是一个1字节的字符,数据可以是0字节到500字节。

我正在使用 sendto 发送缓冲区,recvfrom 在另一端接收缓冲区。

我如何在接收端收到我的seqnumber和数据?我对 C 和 Socket 编程很陌生。感谢您的帮助。

我的第一个建议是在填充和发送缓冲区之前将缓冲区清零,以避免出现垃圾值。你需要定义一个协议——你只能通过网络发送和接收原始字节。使接收端将第一个字节解释为序列号,将其余字节解释为实际消息本身。这可以通过简单地将 recvbuffer 转换为 struct data_packet 来完成,因为底层字节布局是相同的。

可能的问题:

由于 struct 填充,代码可能会超出其范围。

struct data_packet{
   unsigned char seqnumber; 
   // There maybe padding here.
   char data[500]; 
   // There maybe padding here.
}

struct data_packet packettosend; 
char buffer[501];  // May be too small for `packettosend`
memcpy(buffer, &packettosend, sizeof(packetosend)); 

备选方案:使 buffer[] 足够大

// char buffer[501];
char buffer[sizeof packetosend];

只发送数据而不发送任何填充:

使用特定于实现的关键字(如果可用)打包数据

// struct data_packet{
packed struct data_packet{

或执行2次发送

int s1 = sendto(socketfd, &buffer.seqnumber, sizeof buffer.seqnumber, ...);
int s2 = sendto(socketfd, buffer.data, sizeof buffer.data, ...);

或仔细复制

#define SEQ_DATA (sizeof buffer.seqnumber + sizeof buffer.data)
char buffer[SEQ_DATA]; 
memcpy(buffer, &buffer.seqnumber, sizeof buffer.seqnumber);
memcpy(buffer + sizeof buffer.seqnumber, buffer.data, sizeof buffer.data);
int s = sendto(socketfd, buffer, sizeof buffer, ...);

调整 recvbuffer[] 大小以匹配。

我同意 Dennis Afanasev 的观点。详细说明转换策略,读取所有 501 个字节(包括 partial/incomplete 读取),然后转换为指针变量,例如:

struct data_packet *dataRecv = (struct data_packet *)&recvbuffer[0];

然后您可以取消引用 dataRecv 以访问该结构,如 dataRecv->seqnumber 和 dataRecv->data。