首先在msdn上查找htons、 htonl、 ntohl、 ntohs几个函数的说明介绍,它们是用来转换本地计算机和网络计算机字节序的;
那么,它们一定可以用来出来字节序问题(抛开网络流不谈):
上述的“htons”中的“h”是host主机端,“n”是network网络端。
网络传输是使用大端字节序的(先发送高字节,后发送低字节),即“htons”中的“n”是大端的,因此hton类型的函数是“小端-->大端”,ntoh类型的函数是“大端-->小端”
(在实现时,hton就是ntoh,后面说明)
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")
void main()
{
unsigned long u = ntohl(0x11223344);
printf("%x\n", u); <span style="BACKGROUND-COLOR: #999900">//u == 0x44332211</span>
}
引申:
1. 在网络上传输字节流时,比如两台x86计算机传输时,不管两台计算机同时安装的时dos、linux、windows、wince等等,或者分别安装不同的系统,只要cpu平台相同,那么按照透明的格式传输即可,就是用不到上述这几个函数,怎么样的方式发送,怎么样的方式接收,就能保证数据是正确的;
也就是说,x86平台是小端的,ARM平台是小端的,而PowerPC平台是大端的,在不同CPU平台通信是要特别注意。
例如,一个帧串,一般的最后两个字节(通常用unsigned short表达)都是前面串的累加和,大端和小端不同的平台架构按照相同的累加算法,计算出的累加和是不同的!!
2. 判断小端还是大端的函数:
bool am_little_endian ()
{
unsigned short i=1;
return (int)*((char *)(&i)) ? true : false;
}
int main()
{
if(am_little_endian())
{
printf("本机字节序为小段序!\n");
}
else
{
printf("本机字节序为大段序!\n");
}
return 0;
}
3. 大端和小端转换宏定义: htons或者ntohs都定义为SWAP16,使用者自己决定当前环境工作大端还是小端下。
typedef unsigned short uint16;
typedef unsigned int uint32;
#define SWAP16(A) ((((uint16)(A) & 0xff00) >> 8) | \
(((uint16)(A) & 0x00ff) << 8))
#define SWAP32(A) ((((uint32)(A) & 0xff000000) >> 24) | \
(((uint32)(A) & 0x00ff0000) >> 8) | \
(((uint32)(A) & 0x0000ff00) << 8) | \
(((uint32)(A) & 0x000000ff) << 24))
64位:
typedef unsigned long long uint64;
#define SWAP64(val) ((uint64) ( \
(((uint64) (val) & (uint64) (0x00000000000000ff)) << 56) |\
(((uint64) (val) & (uint64) (0x000000000000ff00)) << 40) | \
(((uint64) (val) & (uint64) (0x0000000000ff0000)) << 24) | \
(((uint64) (val) & (uint64) (0x00000000ff000000)) << 8) | \
(((uint64) (val) & (uint64) (0x000000ff00000000)) >> 8) | \
(((uint64) (val) & (uint64) (0x0000ff0000000000)) >> 24) | \
(((uint64) (val) & (uint64) (0x00ff000000000000)) >> 40) | \
(((uint64) (val) & (uint64) (0xff00000000000000)) >> 56)))