我有几个结构被定义为通过不同的操作系统(tcp网络)发送。 定义的结构是:
struct Struct1 { uint32_t num; char str[10]; char str2[10];}
struct Struct2 { uint16_t num; char str[10];}
typedef Struct1 a;
typedef Struct2 b;
数据存储在文本文件中。 数据格式如下:
Struct1 a存储为3个独立的参数。但是,struct2是两个独立的参数,第二行和第三行都存储在char str []中。问题是当我通过多个网络写入服务器时,数据未正确接收。有许多空间可以分隔结构中的不同参数。当我写入服务器时,如何确保正确的发送和填充?如何正确存储数据(动态缓冲区或固定缓冲区)?
写例:write(fd,& a,sizeof(typedef struct a));这是对的吗?
struct2的问题接收侧输出:
正确输出
123(馅饼,地壳)
答案 0 :(得分:10)
write(fd,&a, sizeof(a));
不正确;至少不可移植,因为C编译器可能在元素之间引入填充以确保正确对齐。 sizeof(typedef struct a)
甚至没有意义。
如何发送数据取决于协议的规格。特别是,协议定义了发送字符串的各种方式。分别发送struct
成员通常最安全;通过多次写入或writev(2)
调用。例如,发送
struct { uint32_t a; uint16_t b; } foo;
通过网络,foo.a
和foo.b
已经具有正确的字节顺序,您可以执行以下操作:
struct iovec v[2];
v[0].iov_base = &foo.a;
v[0].iov_len = sizeof(uint32_t);
v[1].iov_base = &foo.b;
v[1].iov_len = sizeof(uint16_t);
writev(fp, v, 2);
答案 1 :(得分:3)
通过网络发送结构非常棘手。您可能遇到以下问题
如果性能不是您的目标,我建议为每个要发送和接收的结构创建编码器和解码器(ASN.1,XML或自定义)。如果确实需要性能,你仍然可以使用结构并通过修复字节序(即网络字节)来解决(1) 确保你的整数存储在这些结构中,并且(2)通过修复编译器并使用pragma或属性来强制执行" packed"结构
Gcc例如使用属性((打包)):
struct mystruct {
uint32_t a;
uint16_t b;
unsigned char text[24];
} __attribute__((__packed__));
(3)不容易解决。在网络协议上使用空终止字符串 并且取决于它们存在会使您的代码容易受到多次攻击。如果需要涉及字符串,我可以使用适当的编码方法,例如上面建议的方法。
答案 2 :(得分:1)
简单的方法是为每个结构编写两个函数:一个用于从文本表示转换为结构,另一个用于将结构转换回文本。然后,您只需通过网络发送文本,然后在接收方将其转换为您的结构。这样的字节顺序无关紧要。
答案 3 :(得分:1)
有转换函数可确保网络中二进制整数的可移植性。使用htons,htonl,ntohs和ntohl将16位和32位整数从主机转换为网络字节顺序,反之亦然。