在 C 中通过套接字传递结构 [英] Passing a structure through Sockets in C
问题描述
我试图将整个结构从客户端传递到服务器,反之亦然.让我们假设我的结构如下
I am trying to pass whole structure from client to server or vice-versa. Let us assume my structure as follows
struct temp {
int a;
char b;
}
我正在使用 sendto 并发送结构变量的地址并在另一端使用 recvfrom 函数接收它.但是我无法获得接收端发送的原始数据.在 sendto 函数中,我将接收到的数据保存到 struct temp 类型的变量中.
I am using sendto and sending the address of the structure variable and receiving it on the other side using the recvfrom function. But I am not able to get the original data sent on the receiving end. In sendto function I am saving the received data into variable of type struct temp.
n = sendto(sock, &pkt, sizeof(struct temp), 0, &server, length);
n = recvfrom(sock, &pkt, sizeof(struct temp), 0, (struct sockaddr *)&from,&fromlen);
其中 pkt 是 struct temp 类型的变量.
Where pkt is the variable of type struct temp.
尽管我收到了 8 字节的数据,但如果我尝试打印,它只是显示垃圾值.任何帮助修复它?
Eventhough I am receiving 8bytes of data but if I try to print it is simply showing garbage values. Any help for a fix on it ?
注意: 无需使用第三方库.
我对这个序列化概念真的很陌生..但是如果不进行序列化,我就不能通过套接字发送结构吗?
I am really new to this serialization concept .. But without doing serialization cant I send a structure via sockets ?
当我尝试使用 sendto 和 recvfrom 函数发送字符串或整数变量时,我收到了数据正确地在接收端.为什么不是在结构的情况下?如果我不必使用序列化功能,那么我应该单独发送结构的每个成员吗?这确实不是一个合适的解决方案,因为如果有n"个成员,那么就会添加n"行代码来发送或接收数据.
When I try to send a string or an integer variable using the sendto and recvfrom functions I am receiving the data properly at receiver end. Why not in the case of a structure? If I don't have to use serializing function then should I send each and every member of the structure individually? This really is not a suitable solution since if there are 'n' number of members then there are 'n' number of lines of code added just to send or receive data.
推荐答案
这是一个非常糟糕的主意.二进制数据应始终以以下方式发送:
This is a very bad idea. Binary data should always be sent in a way that:
- 处理不同的endianness
- 处理不同的填充
- 处理字节大小的差异
永远不要以二进制方式编写整个结构,不要写入文件,也不要写入套接字.
Don't ever write a whole struct in a binary way, not to a file, not to a socket.
始终单独写入每个字段,并以相同的方式读取它们.
Always write each field separately, and read them the same way.
你需要像
unsigned char * serialize_int(unsigned char *buffer, int value)
{
/* Write big-endian int value into buffer; assumes 32-bit int and 8-bit char. */
buffer[0] = value >> 24;
buffer[1] = value >> 16;
buffer[2] = value >> 8;
buffer[3] = value;
return buffer + 4;
}
unsigned char * serialize_char(unsigned char *buffer, char value)
{
buffer[0] = value;
return buffer + 1;
}
unsigned char * serialize_temp(unsigned char *buffer, struct temp *value)
{
buffer = serialize_int(buffer, value->a);
buffer = serialize_char(buffer, value->b);
return buffer;
}
unsigned char * deserialize_int(unsigned char *buffer, int *value);
或者等价物,当然有几种方法可以在缓冲区管理等方面进行设置.然后您需要执行序列化/反序列化整个结构的更高级别的函数.
Or the equivalent, there are of course several ways to set this up with regards to buffer management and so on. Then you need to do the higher-level functions that serialize/deserialize entire structs.
这假设序列化是在缓冲区中完成的,这意味着序列化不需要知道最终目标是文件还是套接字.这也意味着您要支付一些内存开销,但出于性能原因,这通常是一个很好的设计(您不想对套接字的每个值执行 write()).
This assumes serializing is done to/from buffers, which means the serialization doesn't need to know if the final destination is a file or a socket. It also means you pay some memory overhead, but it's generally a good design for performance reasons (you don't want to do a write() of each value to the socket).
完成上述操作后,您可以通过以下方式序列化和传输结构实例:
Once you have the above, here's how you could serialize and transmit a structure instance:
int send_temp(int socket, const struct sockaddr *dest, socklen_t dlen,
const struct temp *temp)
{
unsigned char buffer[32], *ptr;
ptr = serialize_temp(buffer, temp);
return sendto(socket, buffer, ptr - buffer, 0, dest, dlen) == ptr - buffer;
}
以上几点需要注意:
- 要发送的结构首先被序列化,逐个字段,放入
buffer
. - 序列化例程返回一个指向缓冲区中下一个空闲字节的指针,我们用它来计算它序列化的字节数
- 显然,我的示例序列化例程不能防止缓冲区溢出.
- 如果
sendto()
调用成功,则返回值为 1,否则为 0.
- The struct to send is first serialized, field by field, into
buffer
. - The serialization routine returns a pointer to the next free byte in the buffer, which we use to compute how many bytes it serialized to
- Obviously my example serialization routines don't protect against buffer overflow.
- Return value is 1 if the
sendto()
call succeeded, else it will be 0.
这篇关于在 C 中通过套接字传递结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!