我想整个结构传递从客户端到服务器或反之亦然。 让我们假设我的结构如下
struct temp {
int a;
char b;
}
我使用SENDTO和发送所述结构变量的地址,并使用recvfrom函数接收它在另一侧上。 但我没能获得在接收端发送的原始数据。 在SENDTO功能,我接收到的数据保存到类型结构温度的变化。
n = sendto(sock, &pkt, sizeof(struct temp), 0, &server, length);
n = recvfrom(sock, &pkt, sizeof(struct temp), 0, (struct sockaddr *)&from,&fromlen);
其中PKT是类型结构温度的变化。
Eventhough我接收数据的8个字节,但如果我尝试打印它只是显示垃圾值。 任何帮助就可以修复?
注: 没有第三方库都可以使用。
EDIT1:我真的很新的这系列化概念。但没有做系列化着我通过套接字发送结构?
EDIT2:当我尝试发送一个字符串或使用我正确接收在接收器端的数据SENDTO和recvfrom功能的整数变量。 为什么不能在一个结构的情况下? 如果我没有使用序列化功能的话,我应该把每单独结构的每个成员? 这确实是不适合的解决方案,因为如果有成员的“n”个号码,然后有加入的代码行的“n”个数目只是为了发送或接收数据。
这是一个非常糟糕的主意。 二进制数据应该总是以一种发送:
- 处理不同的字节顺序
- 处理不同的填充
- 在手柄的差异固有类型的字节大小
永远不要写一个整体结构以二进制的方式,而不是一个文件,而不是一个插座。
总是分开来写每个字段,并阅读他们以同样的方式。
你需要有类似的功能
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。
使用“附注”组选没有解决我的问题,但我不知道它是否有任何依赖?
#pragma pack(1) // this helps to pack the struct to 5-bytes
struct packet {
int i;
char j;
};
#pragma pack(0) // turn packing off
然后下面的代码行制定了罚款没有任何问题
n = sendto(sock,&pkt,sizeof(struct packet),0,&server,length);
n = recvfrom(sock, &pkt, sizeof(struct packet), 0, (struct sockaddr *)&from, &fromlen);
如果你不想自己写的序列化代码,找到一个妥善的序列化框架,并使用它。
也许谷歌的协议缓冲区将是可能的?
有没有必要写自己的序列化程序short
和long
整数类型-使用htons()
/ htonl()
POSIX功能。
序列化是一个好主意。 您也可以使用Wireshark的监测交通并了解在实际的数据包通过。
相反连载并根据第三方的库它很容易想出了使用标签,长度和值原始协议。
Tag: 32 bit value identifying the field
Length: 32 bit value specifying the length in bytes of the field
Value: the field
根据需要拼接。 使用枚举的标签。 并使用网络字节序...
易编码,便于进行解码。
此外,如果你使用TCP记住它是数据流 ,如果你发送如3个数据包,所以你不一定会得到3个数据包。 他们也许可以“合并”成视NODELAY /格尔算法除其他事项外流,你可以让他们都在同一个recv的......你需要使用RFC1006来分隔数据的例子。
UDP是容易,您会收到我们发送的每个数据包不同的数据包,但它少了很多安全。
如果要传输的数据格式是非常简单的,然后转换为和ANSI字符串是简单便携。