这是一个非常糟糕的主意。二进制数据应始终以以下方式发送:
永远不要以二进制方式编写整个结构,不要写入文件,不要写入套接字。
始终分别编写每个字段,并以相同的方式读取它们。
你需要有这样的功能
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);
或者等价的,当然有几种方法可以设置缓冲区管理等。然后您需要执行序列化/反序列化整个结构的更高级别的函数。
这假设序列化是从缓冲区完成的,这意味着序列化不需要知道最终目标是文件还是套接字。这也意味着您需要支付一些内存开销,但出于性能原因,这通常是一个不错的设计(您不想将每个值都写入套接字)。
完成上述操作后,以下是序列化和传输结构实例的方法:
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
.
- 序列化例程返回一个指向缓冲区中下一个空闲字节的指针,我们用它来计算它序列化到多少字节
- 显然,我的示例序列化例程不能防止缓冲区溢出。
- 如果调用成功则返回值为 1
sendto()
,否则返回值为 0。