结构体和网络字节序问题

大耳 2006-04-29 08:46:37
typedef struct STag{
char a0;
char aa[4];
unsigned short a1;
unsigned short b;
unsigned short c;
int d;
float e;
double f;

char *g;
int *h;
}S;


linux下,
上面这个结构要通过网络传输出去,问如何处理结构填充空洞和网络字节序。
如果哪位 高手能写出大致的伪代码 ?

3x

...全文
572 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
fierygnu 2006-04-29
  • 打赏
  • 举报
回复
* 如果没有对齐,在发送的时候会不会把空洞里面的数据发出去呢?
===
会。send不区分结构,只是当作字节流。

* 浮点型呢怎么办?
===
也需要转换。到网上搜一下,有转换函数库。
fierygnu 2006-04-29
  • 打赏
  • 举报
回复
没找到为什么结贴了?:)
http://schwehr.org/software/density/
大耳 2006-04-29
  • 打赏
  • 举报
回复
现在问题是

* 如果没有对齐,在发送的时候会不会把空洞里面的数据发出去呢?

* 浮点型呢怎么办?
S.f = htonl((unsigned long)f); //这样就可以了?但是把double f变成unsigned long会不会使数据出错

高手帮忙看看,我也马上试验下看
大耳 2006-04-29
  • 打赏
  • 举报
回复
或者
toSend[0] = S.a0; // char a0;
toSend[1] = aa[0]; //char aa[4];
...
toSend[6] = htons(a1); // ; 这里强制转换,会自动把a1的低位放到toSend[7]??

或者再定义一个
S.a1 = htons(a1); 然后发送S=====这样似乎比较好,

但是
浮点型呢怎么办?
S.f = htonl((unsigned long)f); //这样就可以了?但是把double f变成unsigned long会不会使数据出错?
大耳 2006-04-29
  • 打赏
  • 举报
回复
如果没有对齐,在发送的时候会不会把空洞里面的数据发出去呢?


考虑移植性,应该使用htonl等函数,就是说,要另外建立一个数组,然后把结构一个一个的处理后,填入?
S myS;
unsigned char toSend[sizeof(S)]; // 这个sizeof得到的会比我要发的数据大呀?
然后
toSend[0] = S.a0; // char a0;
toSend[1] = aa[0]; //char aa[4];
...
toSend[6] = a1 // unsigned short a1; 这里强制转换,会自动把a1的低位放到toSend[7]??
// 或者用 toSend[6] = a1 & 0xff;
// toSend[7] = (a1>>8) & oxff;
.
.
.

x86 2006-04-29
  • 打赏
  • 举报
回复
如果你的所有机器的系统都是一样的,也就是肯定没有字节序不一致的情况,可以不考虑字节序的问题(比如如果都是x86体系,就不用考虑)。否则就需要对每个结构成员调用htonl或者ntohl函数在网络字节和本地字节之间转换。
x86 2006-04-29
  • 打赏
  • 举报
回复
你可以把char和short都换成int,就可以对齐了。或者char后面加上一个char reserved[3]凑齐4字节。
大耳 2006-04-29
  • 打赏
  • 举报
回复
ps 系统存储器是4字节对齐的
大耳 2006-04-29
  • 打赏
  • 举报
回复
还是不行哎~~~

调用htonf 时必须把参数强制转换为unsigned long,
这样做和调用htonl没什么区别了,

所以可是 (unsigned long )0.5 ===> 0

好郁闷呀
fierygnu 2006-04-29
  • 打赏
  • 举报
回复
浮点数的格式虽然有IEEE标准,但不是大家都用。
大耳 2006-04-29
  • 打赏
  • 举报
回复
呵呵,找到了,多谢多谢

#define htonf(x) (endian()?(x):swapf(x))

static int
endian()
{
static int init = 0;
static int endian_value;
char *p;

if (init) return endian_value;
init = 1;
p = (char*)&init;
return endian_value = p[0]?0:1;
}

#ifndef swap32
#define swap32(x) ((((x)&0xFF)<<24) \
|(((x)>>24)&0xFF) \
|(((x)&0x0000FF00)<<8) \
|(((x)&0x00FF0000)>>8) )
#endif

其实是自己做字节调换,

只是奇怪 这么重要的函数为什么不是 系统函数,


fierygnu 2006-04-29
  • 打赏
  • 举报
回复
呵呵,怎么搜的?google htonf
大耳 2006-04-29
  • 打赏
  • 举报
回复
不过可以肯定的是不能调用htonl来处理浮点型。我试过了,类型转换时,都变成了0 :(
大耳 2006-04-29
  • 打赏
  • 举报
回复
关键是浮点型麻烦, fierygnu(va_list) 大虾说的库没有找到。。。。。失败

tb01412(tb) 说人为调换,对于整形时可以的,但是对于浮点型我要验证下看


tb01412 2006-04-29
  • 打赏
  • 举报
回复
1.用紧凑格式的结构体定义
2.将每个非char类型的成员取出后转成网络字节序然后再发送出去
3.接收到之后将先存临时的结构体中,将所有非CHAR类型的成员转换成本地字节序

只要是一个字节以上的数据结构,都存在字节序的问题,为了简化处理,有一个笨办法,就是将每个非char类型的成员拷到临时变量中,然后再取这个变量地址,如果是PC机,也就是小端字节序,网络是大端字节序,只需操作这个内存地址,将这个内存地址中的数据按char类型调个头,就OK了,接收端在收到后就执行相反的操作,这就是人为地进行字节序转换,无论是整型,浮点型还是其它类型的转换过程都是一样

23,110

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧