3. 结构与数据控制

        好了,我们终于到了这一步。现在开始讨论编程的问题。在这个部分,我会提到到嵌套字接口需要用到的许多不同的数据类型,因为他们中有一部分很难说明。
        先来个简单的:一个嵌套字描述符。嵌套字描述符是这种类型:

    int 

一个普通的int型。
        事情从这里开始变得奇怪了,继续跟我一起看下去。正如所知道的:有两种字节顺序:一个先是最终要的字节(有时称做八位字节)或先是最不重要字节。前者称为 "Network Byte Order"(网络字节顺序)。有些机器内部存数字的时候使用网络字节顺序,但另一些则不是。当我提到某些东西使用网络字节顺序,你必须调用一个函数(比如htons())把这种字节顺序从“Host Byte Order”(主机字节顺序)改变成网络字节顺序。如果我没说网络字节顺序,你就要使用主机字节顺序。
        (很奇怪,网络字节顺序也称为"Big-Endian Byte Order"Big-Endian字节顺序。)
        我的第一个结构体——struct sockaddr。这个结构存储着许多中类型的嵌套字的地址信息。

    struct sockaddr {
        unsigned short    sa_family;    // address family, AF_xxx
        char              sa_data[14];  // 14 bytes of protocol address
    }; 
        sa_family可以代表很多东西,但我们这篇文章中所有的类型都用AF_INET来代替。sa_data 包括了嵌套字的目的地地址和端口号。如果你不想把亲自把地址放入冗长的包中,这会变得很不好用。
        为了处理sockaddr,程序员建立了一个等同的结构:sockaddr_in ("in" 代表 "Internet".)
    struct sockaddr_in {
        short int          sin_family;  // Address family
        unsigned short int sin_port;    // Port number
        struct in_addr     sin_addr;    // Internet address
        unsigned char      sin_zero[8]; // Same size as struct sockaddr
    }; 
This structure makes it easy to reference elements of the socket address. Note that sin_zero (which is included to pad the structure to the length of a struct sockaddr) should be set to all zeros with the function memset(). Also, and this is the important bit, a pointer to a struct sockaddr_in can be cast to a pointer to a struct sockaddr and vice-versa. So even though socket() wants a struct sockaddr*, you can still use a struct sockaddr_in and cast it at the last minute! Also, notice that sin_family corresponds to sa_family in a struct sockaddr and should be set to "AF_INET". Finally, the sin_port and sin_addr must be in Network Byte Order!