2015/11/24

socket中几个重要结构体


IP地址信息结构体

此数据结构用做 bind、connect、recvfrom、sendto 等函数的参数,指明地址信息。但一般编程中并不直接针对此数据结构操作,而是使用另一个与sockaddr等价的数据结构(sockaddr_insockaddr_in6

struct sockaddr {
    unsigned short  sa_family;      /* address family, AF_xxx */
    char            sa_data[14];    /* 14 bytes of protocol address */
};
sa_family(地址族,也就是 IP 地址类型) 解释
AF_INET 2 AF 是"Address Family"的简写,INET是"Inetnet"的简写。AF_INET 表示 IPv4 地址,例如 127.0.0.1
AF_INET6 23 表示 IPv6 地址,例如 1030::C9B4:FF12:48AA:1A2B
AF_UNSPEC 0 协议无关

IPV4地址信息结构体

struct sockaddr_in {
    short int           sin_family;     /* Address family; must be AF_INET. */
    unsigned short int  sin_port;       /* Port number */
    struct in_addr      sin_addr;       /* Internet address */
    unsigned char       sin_zero[8];    /* Same size as struct sockaddr */ //是为了让 sockaddr 与 socketaddr_in 两个数据结构保持大小相同而保留的空字节
};

struct in_addr {
    uint32_t s_addr; //ip地址 通过 inet_addr(ipstr) 将一个点分十进制的IP(eg:192.168.1.101)转换成一个长整数型数
};

IPV6地址信息结构体

struct sockaddr_in6 {
    short               sin6_family;        /* Address family; must be AF_INET6. */
    u_short             sin6_port;          /* Transport-level port number */
    u_long              sin6_flowinfo;      /* Ipv6 flow information. */
    struct in6_addr     sin6_addr;          /* Ipv6 address. */
    u_long              sin6_scope_id;      /* Set of interfaces for a scope. */
};

struct in6_addr {
    union {
        u_char      Byte[16];       /* Host address formatted as 16 u_chars. */
        u_short     Word[8];        /* Host address formatted as 8 u_shorts. */
    } u;
};

addrinfo结构体

struct addrinfo {
    int                 ai_flags;       /* customize behavior */
    int                 ai_family;      /* address family */
    int                 ai_socktype;    /* socket type */
    int                 ai_protocol;    /* protocol */
    size_t              ai_addrlen;     /* length in bytes of address */
    struct sockaddr     *ai_addr;       /* address */
    char                *ai_canonname;  /* canonical name of host */
    struct addrinfo     *ai_next;       /* next in list */
};
ai_flags 解释
AI_ADDRCONFIG 32 查询配置的地址类型(IPV4或IPV6)
AI_ALL 16 查找IPV4和IPV6地址
AI_PASSIVE 1 套接字地址用于监听绑定
AI_CANONNAME 2 用于返回主机的规范名称
AI_NUMERICHOST 4 地址为数字串

ai_protocol

协议(Protocol)就是网络通信的约定,通信的双方必须都遵守才能正常收发数据。协议有很多种,例如 TCP、UDP、IP 等,通信的双方必须使用同一协议才能通信。协议是一种规范,由计算 机组织制定,规定了很多细节,例如,如何建立连接,如何相互识别等。

协议仅仅是一种规范,必须由计算机软件来实现。例如 IP 协议规定了如何找到目标计算机,那么各个开发商在开发自己的软件时就必须遵守该协议,不能另起炉灶。

所谓协议族(Protocol Family),就是一组协议(多个协议)的统称。最常用的是 TCP/IP 协议族,它包含了 TCP、IP、UDP、Telnet、FTP、SMTP 等上百个互为关联的协议,由于 TCP、IP 是两种常用的底层协议,所以把它们统称为 TCP/IP 协议族。

ai_socktype(数据传输协议) 解释
IPPROTO_IP 0 IP协议
IPPROTO_IPV4 4 IPv4
IPPROTO_IPV6 41 IPv6
IPPROTO_UDP 17 UDP 传输协议
IPPROTO_TCP 6 TCP 传输协议

ai_socktype(数据传输方式) 解释
SOCK_STREAM 1 表示面向连接的数据传输方式。
SOCK_DGRAM 2 表示无连接的数据传输方式

getaddrinfo() 函数

getaddrinfo() 函数能够处理域名到IP地址以及进程服务名到端口这两种转换,返回的是一个sockaddr结构的链表而不是一个地址清单。这些sockaddr结构随后可由套接口函数直接使用。 如此一来,getaddrinfo函数把协议相关性安全隐藏在这个库函数内部。应用程序只要处理由getaddrinfo函数填写的套接口地址结构。

int getaddrinfo(
                    const char              *node,
                    const char              *service,
                    const struct addrinfo   *hints,
                    struct addrinfo         **res
                );

node:指向一个主机名(域名)或者地址串(IPv4的点分十进制串或者IPv6的16进制串)。

service:指向一个10进制端口号数串,或者是已定义的服务名称,如ftp、http等。

node,service 不能同时为NULL。

hints:它可以是一个空指针,也可以是一个指向某个addrinfo结构的指针,调用者在这个结构中填入关于期望返回的信息类型的线索。


Linux下一切皆为文件

在 Linux 中,一切都是文件,除了文本文件、源文件、二进制文件等,一个硬件设备也可以被映射为一个虚拟的文件,称为设备文件。例如,stdin 称为标准输入文件,它对应的硬件设备一般 是键盘,stdout 称为标准输出文件,它对应的硬件设备一般是显示器。对于所有的文件,都可以使用 read() 函数读取数据,使用 write() 函数写入数据。

“一切都是文件”的思想极大地简化了程序员的理解和操作,使得对硬件设备的处理就像普通文件一样。所有在 Linux 中创建的文件都有一个 int 类型的编号,称为文件描述符(File Descriptor)。 使用文件时,只要知道文件描述符就可以。例如,stdin 的描述符为 0,stdout 的描述符为 1

在 Linux 中,socket 也被认为是文件的一种,和普通文件的操作没有区别,所以在网络数据传输过程中自然可以使用与文件 I/O 相关的函数。可以认为,两台计算机之间的通信,实际上是两个 socket 文件的相互读写。