资源描述:
《Linux网络编程-多字节数据的收发》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
1、Linux网络编程-多字节数据的收发.txt珍惜生活——上帝还让你活着,就肯定有他的安排。雷锋做了好事不留名,但是每一件事情都记到日记里面。Linux网络编程一步一步学-多字节数据的收发首先,必须说明的是网络上的数据是流式传送的,也就是经常说的stream,流式传送的特点就是一方发送的是1234四个字节,那么接收端收到的必然是1234四个字节,顺序完全相同。其次,必须说明的是主机字节序,不同CPU保存数据的方式不同,即高位在前还是低位在前的问题的,大家可以自己google搜索一下“biglittleendianCPU”会发现很多
2、人解释这个问题。对于单个字节的数据,即存储空间占用1Byte的数据,没有任何问题,但由于数据很大,通常1Byte表示不了,就必须引入多字节表示的数据,比如一个int通常为32个bit的数据,即4Byte表示一个int,那么当你定义一个int型变量x时,它的值可能是0x1234,即x=0x1234;但如果是另外一种顺序,则x=0x4321,显然这两个数相差很大。big-endian和little-endian问题简单说来就是对于同样的4个字节1234,一种顺序表示为1234,另一种顺序可能表示为4321。这就象中文表示姓名和英文表
3、示姓名的顺序不一样,中国人姓名表示时姓在前名在后,而英文习惯里表示姓名时名在前姓在后,对于汉语的zhoulifa,英文里可能写成lifazhou。如果双方不知道这个差别,英文习惯的人听汉语的人说人名zhoulifa里必然以为是姓lifa的叫zhou的人。你可以用这个程序来测试你的主机字节序:#include#includeintmain(void){printf("big:%dlittle:%dmine:%d",__BIG_ENDIAN,__LITTLE_ENDIAN,__BYTE_OR
4、DER);return0;}因此,基于上述两点我们就明白了“多字节数据传送必须要关注数据顺序”。对于单字节的数据,比如char型的,没有问题,所以在前面所有例子程序中,一个程序发送“hello,Linux”,另一个程序必然同样收到这样的字符串而不会顺序乱了。但如果你在这边发过去四个字节1234表示一个int数据,对方接收到以后不知道你的机器是big-endian还是little-endian,按照它自己的理解来解释这个数字,可能这个数字就是4321了。好在前人已经想到这个问题了,因此网络编程基础“TCP/IP协议”里已经规定所有
5、在网络上传送的数据统一采用big-endian顺序。因此,正确的网络编程方法是这样的:如果你要发送纯字符串给对方,那么相当容易,可以这样:charbuf[]="Thisisateststring";......ret=send(socket_fd,buf,strlen(buf),0);......如果你要发送多字节数据,比如short,int,float,double,long……你必须先转换为big-endian序再发送,比如:intage=30;……age=htonl(age);ret=send(socket_fd,(voi
6、d*)&age,sizeof(int),0);……这里涉及一些网络字节序和主机字节序转换的函数,把主机(host)字节序转换为网络(network)字节序用到htons,htonl等函数,反之则用ntohs,ntohl等函数。man一下就知道这几个函数的用处和用法了。对于结构数据的传送比如有这样一个表示人员信息的结构:structmember{charname[32];intage;chargender;charaddress[128];};当你定义了一个变量structmemberpersonalInfo并把personalI
7、nfo的各字段内容准备好了,如何把这个信息发送给对方呢?一种方法:发送和接收的双方都知道上述结构structmember的定义,因此,不管一个人的名字是几个字节,也不管这个人的住址信息是多少个字节,发送的一方可以这样写程序:structmemberpersonalInfo;......ret=send(socket_fd,personalInfo.name,32,0);......personalInfo.age=htonl(personalInfo.age);ret=send(socket_fd,(void*)&persona
8、lInfo.age,sizeof(int),0);......ret=send(socket_fd,&personalInfo.gender,sizeof(char),0);......ret=send(socket_fd,personalInfo.addres