15.2.10 主机字节序和网络字节序
当在基于intel处理器的linux机器上运行新版本的服务器和客户程序时,可以用netstat命令查看网络连接状况.它显示了客户/服务器连接正在等待关闭.连接将在一段超时间之后关闭,如下所示:
可以看到这条连接对应的服务器和客户的端口号.local address一栏显示的是服务器,而foreign address一栏显示的是远程客户(即使是在同一台机器上,它仍然是通过网络连接的).为了确保所有套接字都是不同的,这些客户端口一般都与服务器监听套接字不同,并且在这台计算机上是唯一的.
可是,显示的本地地址(服务器套接字)端口号是1574,而选择的是9734.为什么不一样呢?原因是,通过套接字接口传递的端口号和地址都是二进制数字,不同的计算机使用不同的字节序来表示整数.例如,Intel处理器将32位的整数分为4个连续的字节,并以字节序1-2-3-4存储在内存中,这里的1表示最高位的字节.而IBM PowerPC处理器是以字节4-3-2-1的方式存储整数.如果保存整数的内存只是以逐个字节的方式来复制,两个不同的计算机得到的整数值就会不一致.
为了使不同类型的计算机可以通过网络传输的多字节整数的值达成一致,需要定义一个网络字节序,客户和服务器程序必须在传递之前,将它们的内部整数表示方式转换为网络字节序.它们通过定义在头文件netinet/in.h中的函数来完成这一工作.这些函数如下所示:
#include <netinet/in.h> unsigned long int htonl(unsigned long int hostlong); unsigned short int htons(unsigned short int hostshort); unsigned long int ntohl(unsigned long int netlong); unsigned short int ntohs(unsigned short int netshort);
这些函数将16位整数和32位整数在主机字节序和标准的网络字节序之间进行转换.函数名是与之对应的转换操作的简写形式.例如"host to network, long"(hton,长整数从主机字节序到网络字节序的转换)和"host to network, short"(htons,短整数从主机字节序到网络字节序的转换).如果计算机本身的主机字节序和网络字节序相同,这些函数的内容实际上就是空操作.
为了保证16位的端口号有正确的字节序,服务器和客户需要这些函数转换端口地址.新服务器程序server3.c中的改动是:
server_address.sin_addr.s_addr = htol(INADDR_ANY); server_address.sin_port = htons(9734);
不需要对函数调用inet_addr("127.0.0.1")进行转换,因为inet_addr已被定义为产生一个网络字节序的结果.新程序client3.c中的改动是:
address.sin_port = htons(9734);
服务器也做了改动,通过INADDR_ANY来允许到达服务器任一网络接口的连接.
运行server3和client3时,看到如下所示:
使用netstat -A inet将看到本地连接使用的是正确的端口:
版权声明:本文为博主原创文章,未经博主允许不得转载。