htonl,htons 和 ntohs相关问题

本文深入探讨了网络字节序在socket编程中的重要性,详细解释了htonl, htons以及ntohs函数的作用。通过实例展示了如何在Delphi和Windows环境下正确使用这些转换函数,确保在网络通信中数据的一致性。同时,内容涵盖了这些函数在网络编程中的常见问题和解决方案,对于理解图像数据在网络传输中的处理也具有参考价值。" 132246304,19671681,Android中的wpa_supplicant Wi-Fi身份验证,"['Android', 'Wi-Fi', '安全']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

htonl函数是一个网络转换的函数,他把不确定的一个32位数字,转换成网络通用的32位数字,即大头在后的方式。

我们一般使用的计算机都是大头在后,也就是高地址在后面的形式。
比如你定义一个整型变量
int i = 0x12345678
然后在定义一个整型指针
int *p = &i;

假设p的地址是0x0012f2ec
那么在这个地址后4个字节都是这个整数,他的存放形式为


如果是大头前,也就是高地址在前,则存放形式为
0x0012f2ec:12 34 56 78

使用htonl函数后,他的存放形式就便为
0x0012f2ec:78 56 34 12


需要根据操作系统的不同确定你是否需要使用。

****************************************************************************

htonl = Host To Network, type Long
ntohl = Network To Host, type Long
同理,还有 htons 和 ntohs,这里的 s 是指 short

/***************************************************************************/

x86系统的数据存放都是按照little-endian的格式(硬件层没有对字节序的区分机制)。
通过对Windows平台的字节序转换函数(htons/ntohs(16bit),htonl /ntohl(32bit))的代码的分析,发现Windows对这样的转换没有进行特别的字节序检测,仅仅简单的进行了高低位的转换。

至于为什么没有做检测。我的理解是些转换函数已经默认了参数的字节序(MSDN)。
对于htons,htonl的参数为host byte order(小头);
对于ntohs,ntohl的参数为network byte order(大头)

其实,在调用函数时,我们就隐含指定了数值(注意,可能并非我们定义的数值)。
上面的程序中,可以这样理解。
d = htonl(c);
将小头存放(78’56’34’12)的数值0x12345678 转换为大头存放(12’34’56’78),并附给d。
注意:虽然这时d在小头系统中为0x78563412,但真实的数值是大头序的0x12345678。
e = ntohl(c);
将大头存放(78’56’34’12)的数值0x78563412 转换为小头存放(12’34’56’78),并附给e。

综上所述,导致这个疑问有以下几点。
1.字节序转换函数默认了被转换参数的字节序,所以没有必要再进行检测。
2.对转换后的数值的误解。(d的数值应为0x12345678,而非0x78563412)
3.调用ntohl函数时,对于参数的指定存在误解。
e = ntohl(0x78563412); /*数值0x12345678应该这样指定*/


对于htonl /ntohl代码一样的问题,属x86系统的特例。
如果,有这样一种字节序系统1’3’4’2,对于数值0x12345678的保存形式应该是12’56’78’34。
这个系统上的htonl /ntohl関数的实现应该不会一样的。
也许DiabloWalkOnTheEarth(WorldOfWg( 狗城是个烂代理 )) 所说的机器就是这么一种“非little/big-endian”的字节序,呵呵。


To 0delphi(睡个舒服觉)

的确判别一个 系统 是大头序还是小头序的方法是有的。
比如:
-BEGIN-
int x=1; // 0x00000001
if (*(char*)&x) {
/* little endian. memory image 01 00 00 00 */
}else{
/* big endian. memory image 00 00 00 01 */
}
-END-
内存数据(0x00000001)-〉大头/小头字符序-〉数值(1)
这里判别的前提条件是知道内存数据及所对应的数值,所以可以判定出大小头字符序。  
/*************************************************************************************************************/

字节顺序
不同的计算机处理数字有两种形式,big-endian和little-endian型式(
little-endian格式的数据,例如0X12345678以(0X78 0X56 0X34 0X12)方式保存、
big-endian格式的数据,例如0X12345678以(0X12 0X34 0X56 0X78)方式保存 ),这依赖于他们是怎么设计的,比如Intel的x86处理器,多字节是用little-endian型式。IP地址和和端口在电脑中是多字节存放的,他们是host-byte顺序,然而当IP地址和端口通过网络时,必须转成big-endian形式,也就是network-byte顺序
  有一系列函数完成两者之间的转换。比如
host-byte序转network-byte序
u_long htonl(u_long hostlong);
int WSAHtonl( SOCKET s, u_long hostlong, u_long FAR * lpnetlong );
u_short htons(u_short hostshort);
int WSAHtons( SOCKET s, u_short hostshort, u_short FAR * lpnetshort );

network-byte序转host-byte序
u_long ntohl(u_long netlong);
int WSANtohl( SOCKET s, u_long netlong, u_long FAR * lphostlong );
u_short ntohs(u_short netshort);
int WSANtohs( SOCKET s, u_short netshort, u_short FAR * lphostshort );    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值