一起talk C栗子吧(第一百五十三回:C语言实例--socket通信地址系统调用一)

各位看官们,大家好,上一回中咱们说的是计算机中大小端的例子,这一回咱们说的例子是socket通信地址的系统调用 。闲话休提,言归正转。让我们一起talk C栗子吧!

看官们,我们在前面的章回中介绍了套接字的通信地址,这一回中我们将介绍操作套接字通信地址的系统调用。大家都知道套接字的通信地址与套接字的域有关,接下来,我们依据套接字的通信域分别进行介绍。

AF_UNIX域的通信地址

AF_UNIX域的通信地址本质上是文件的目录,文件目录存储在本地计算机中,而且使用该域通信时,通信双方都位于同一台计算机中。大家可以看到,通信地址和通信双方都位于同一台计算机中,这样看来我们不需要担心通信地址是使用大端方法还是小端方法来存储,也不用担心通信过程中传输方式是使用大端方法还是小端方法,因为同一台计算机中的存储方式是固定的。

AF_INET域的通信地址

AF_INET域的通信地址本质上是计算机的IP地址和端口号,它们俩个都存储于本地计算机中,使用该域通信时,通信双方属于不同的计算机,不同的计算机可能会使用不同的存储方式来存储它们的IP地址和端口号,究竟使用大端方法还是小端方法,取决于计算机自身的硬件架构,不过有一点是可以确认的,那就是在通信过程中传输数据时使用的是大端方法。因此,我们在该域中使用套接字通信时,需要考虑计算机大小端存储方式对通信的影响。其实,系统设计者已经想到这点了,它为我们提供了通信地址相关的系统调用,通过这些系统调用可以有效地解决大小端的问题。下面我们将详细介绍这些系统调用。

       uint32_t htonl(uint32_t hostlong);
       uint16_t htons(uint16_t hostshort);
       uint32_t ntohl(uint32_t netlong);
       uint16_t ntohs(uint16_t netshort);

在介绍这些函数前,我们先做一些说明,以方便我们介绍它们:

  • 函数中的h是host的缩写,表示本地计算机中数据的存储方式,该方式可能是大端或者小端中的一种。
  • 函数中的n是network的缩写,表示网络中数据的存储方式,其实就是大端方式。
  • 函数中的s是short的缩写,表示short int类型。
  • 函数中的l是long的缩写,表示long int类型。
  • 函数中的to表示转换的意思。

现在我们来看这些函数中的第一个函数:
htonl从名字中就能看出来,它是h到n的转换,更加准确的说,它是把本地计算机中使用大端或者小端方式存储的数据转换为网络中使用大端方式存储数据。函数末尾的l表示数据的类型为int long。通常我们叫本地计算机中使用大端或者小端方式存储的数据为本地字节序数据,而网络中使用大端方式存储的数据为网络字节序数据。因此,函数htonl表示把本地字节序数据转换为网络字节序数据,数据的类型为long int。

第一个函数介绍完后,我想大家都能推理出其它函数的功能:

  • 函数 htonl()表示把本地字节序数据转换为网络字节数据,数据的类型为int long;
  • 函数 htons()表示把本地字节序数据转换为网络字节数据,数据的类型为int short;
  • 函数 ntohl()表示把网络字节序数据转换为本地字节数据,数据的类型为int long;
  • 函数 ntohs()表示把网络字节序数据转换为本地字节数据,数据的类型为int short;

    这些函数都位于同一个头文件中,使用它们的时候需要包含头文件:#include <arpa/inet.h>。另外,这些函数是智能的,它的智能性体现在数据转换的过程中:如果本地字节序和网络字节序相同,那么它们就不进行转换。看来还是有点小聪明呀,哈哈。接下来我们通过代码来演示一下这些函数的用法:

#include <stdio.h>
#include <arpa/inet.h>

int main()
{
    long int h_data = 0x12345678;
    long int n_data = 0;
    int len = sizeof(long int); // get the count of byte
    int i =-0;
    char *p = (char*)&h_data;

    printf(" host data \n");
    printf(" [address] [value] \n");
    while(i<len)
    {
        printf("[%p] [%x] \n",p+i,*(p+i));
        i++;
    }

    n_data = htonl(h_data); // convert data from host to network
    p = (char*)&n_data;

    printf("\n network data \n");
    printf(" [address] [value] \n");
    i -= len;
    while(i<len)
    {
        printf("[%p] [%x] \n",p+i,*(p+i));
        i++;
    }

    return 0;
}

该例子是在上一回例子的基础上修改的,不同之处在于,我们使用了htonl函数对数据进行了转换。其它的内容就不详细介绍了,相信大家都能看明白。另外,我们只使用了htonl函数,其它几个函数的用法和它的用法完全相同,因此,我们就不一个一个地举例子说明了。

下面是程序的运行结果,请参考:

host  data 
  [address]   [value] 
[0xbfe19a1c]   [78] 
[0xbfe19a1d]   [56] 
[0xbfe19a1e]   [34] 
[0xbfe19a1f]   [12] 

 network data 
  [address]   [value] 
[0xbfe19a20]   [12] 
[0xbfe19a21]   [34] 
[0xbfe19a22]   [56] 
[0xbfe19a23]   [78] 

从上面的运行结果中可以看到,本地字节序数据和网络字节序数据的存储方式正好相反,这也说明了,使用转换函数是很有必要的。

各位看官,关于socket通信地址系统调用的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解 。

你可能感兴趣的:(htonl,htons,ntohl,ntohs)