当前位置: 技术问答>linux和unix
嵌入式linux网络编程的问题
来源: 互联网 发布时间:2016-05-11
本文导语: 我在进行嵌入式linux的socket编程时出现了这样的一个问题 开始的时候service和client都在电脑上运行的时候测试没任何问题,可是把client下载到电路板上和电脑进行通信的时候就出问题了。 传输的包中的short型数据都出...
我在进行嵌入式linux的socket编程时出现了这样的一个问题
开始的时候service和client都在电脑上运行的时候测试没任何问题,可是把client下载到电路板上和电脑进行通信的时候就出问题了。
传输的包中的short型数据都出问题了,高8位和低8位都交换了。电脑上的1传输到板子上后都成了256.
我觉得这和数据存储的优先顺序有关系。
service()
{......
/*set sockaddr_in founctions*/
saddr.sin_family=AF_INET;
saddr.sin_port=htons(SERVPORT); //用的是htons
saddr.sin_addr.s_addr=INADDR_ANY;
bzero(&(saddr.sin_zero),8);
......
}
client()
{......
saddr.sin_family=AF_INET;
saddr.sin_port=htons(SERVPORT); //用的是htons
saddr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(saddr.sin_zero),8);
.......
}
我把两边的htons改成ntohs也没用。
请问是什么问题?
开始的时候service和client都在电脑上运行的时候测试没任何问题,可是把client下载到电路板上和电脑进行通信的时候就出问题了。
传输的包中的short型数据都出问题了,高8位和低8位都交换了。电脑上的1传输到板子上后都成了256.
我觉得这和数据存储的优先顺序有关系。
service()
{......
/*set sockaddr_in founctions*/
saddr.sin_family=AF_INET;
saddr.sin_port=htons(SERVPORT); //用的是htons
saddr.sin_addr.s_addr=INADDR_ANY;
bzero(&(saddr.sin_zero),8);
......
}
client()
{......
saddr.sin_family=AF_INET;
saddr.sin_port=htons(SERVPORT); //用的是htons
saddr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(saddr.sin_zero),8);
.......
}
我把两边的htons改成ntohs也没用。
请问是什么问题?
|
看起来是little endian和big endian的问题。
但未必是,我对网络编程不熟悉,但我想网络编程时的API应该可以屏蔽底层的
endian问题。
这里是简单的检测 little和big endian的程序(摘自 APUE2 Unix环境高级编程第二版)
Figure C.20. Determine byte order on system
#include
#include
#include
int
main(void)
{
uint32_t i;
unsigned char *cp;
i = 0x04030201;
cp = (unsigned char *)&i;
if (*cp == 1)
printf("little-endiann");
else if (*cp == 4)
printf("big-endiann");
else
printf("who knows?n");
exit(0);
}
但未必是,我对网络编程不熟悉,但我想网络编程时的API应该可以屏蔽底层的
endian问题。
这里是简单的检测 little和big endian的程序(摘自 APUE2 Unix环境高级编程第二版)
Figure C.20. Determine byte order on system
#include
#include
#include
int
main(void)
{
uint32_t i;
unsigned char *cp;
i = 0x04030201;
cp = (unsigned char *)&i;
if (*cp == 1)
printf("little-endiann");
else if (*cp == 4)
printf("big-endiann");
else
printf("who knows?n");
exit(0);
}
|
楼上说的有道理,即使是大小端系统交互
网络编程中都可以屏蔽这些差异,因为经过了网络字节序和本地字节序的转换
你传输的是short数据?
为什么要按照8位来访问呢?
short的两个8位在大小端系统上存储的位置正好反了
如果你以八位来读,其就反了
相当于你按照位域的形式来访问short了,此时大小端系统间就是不可以移植的
这是嵌入式程序和PC程序的差异
但若你以short来读,合成后两端的值就是匹配的了
网络编程中都可以屏蔽这些差异,因为经过了网络字节序和本地字节序的转换
你传输的是short数据?
为什么要按照8位来访问呢?
short的两个8位在大小端系统上存储的位置正好反了
如果你以八位来读,其就反了
相当于你按照位域的形式来访问short了,此时大小端系统间就是不可以移植的
这是嵌入式程序和PC程序的差异
但若你以short来读,合成后两端的值就是匹配的了
|
“传输的包中的short型数据都出问题了,高8位和低8位都交换了。电脑上的1传输到板子上后都成了256.”
什么意思?
把你怎么定义数据怎么取数据的过程说明白!!!!
你定义一个short数据,不管其在大端还是小断系统上,
尽管存储格式可能不一样,但只要是short读取,肯定不会变的
///////////
两个办法:
1,做个结构的转化函数;发送之前,接受之后对结构进行转换。
2,结构中不要定义大于1个字节的项。
///////////
要是你这样,大小端系统如果要交互的话还不累死了??如果结构体只能定义char还有意义么?
假设大端系统ARM传递short a=0x1234到小端系统PC
ARM中,&a=0x100,大端系统,高字节放在低地址
则*0x100 = 0x12,*0x101 = 0x34
网络上传递字节流,从低地址开始传递,且为大端模式
ARM到网络,同为大端,无需转换,因此网络上的字节流为0x12,0x34
存放放到PC上时,网络字节序转换后,字节流为0x34,0x12,设b保存a
&b = 0x100000
则*0x100000 = 0x34,*0x100001 = 0x12
高低字节颠倒了,若你以8位访问,则会发现同样是低字节
*0x100 = 0x12 != *0x100000 = 0x34
可是short访问时
*(short *)0x100 = *(short *)0x100000 = 0x1234
什么意思?
把你怎么定义数据怎么取数据的过程说明白!!!!
你定义一个short数据,不管其在大端还是小断系统上,
尽管存储格式可能不一样,但只要是short读取,肯定不会变的
///////////
两个办法:
1,做个结构的转化函数;发送之前,接受之后对结构进行转换。
2,结构中不要定义大于1个字节的项。
///////////
要是你这样,大小端系统如果要交互的话还不累死了??如果结构体只能定义char还有意义么?
假设大端系统ARM传递short a=0x1234到小端系统PC
ARM中,&a=0x100,大端系统,高字节放在低地址
则*0x100 = 0x12,*0x101 = 0x34
网络上传递字节流,从低地址开始传递,且为大端模式
ARM到网络,同为大端,无需转换,因此网络上的字节流为0x12,0x34
存放放到PC上时,网络字节序转换后,字节流为0x34,0x12,设b保存a
&b = 0x100000
则*0x100000 = 0x34,*0x100001 = 0x12
高低字节颠倒了,若你以8位访问,则会发现同样是低字节
*0x100 = 0x12 != *0x100000 = 0x34
可是short访问时
*(short *)0x100 = *(short *)0x100000 = 0x1234
|
如果是串口或者其他途径,那么是需要手动转换
但lz现在就是网络编程,系统已经自动转换了
为什么要进行字节序的转换?
就是为了防止单纯的将字节流按照地址存放
如大端系统short 0x1234,从低地址到高地址的字节流为0x12,0x34
若不进行字节序的转换,则保存到小端系统上
低地址为0x12,高地址为0x34
因为是小端系统,short访问时,认为低地址是低字节,高地址是高字节
则short数据为0x3412
和大端系统上的short不一样
因此字节序的转换就是为了解决这种问题,
这就保证了大端的short 0x1234放在小端上仍然为short 0x1234