linux网络编程系列-地址结构(1)

linux socket编程中经常用到各种类型的地址, 最近在一些开源代码中经常见到, 它们是进行socket编程的基础, 本文对常见的地址结构进行简单整理, 并在附录中对某些函数给出了helloworld式的测试代码, 方便查询.

IPV4地址结构

in_addr

这个结构内部以网络字节序的32位无符号整数表示的ipv4地址, 在后续介绍的地址结构中会用到这个结构. 之所以一个整数也要放在一个结构体中来代表地址, 是历史原因. 一开始这个结构内部不仅仅是一个整数, 后来演化成只有一个整数, 但是这个结构体保留了. 所以要引用一个IPV4地址, 可以传该结构体, 也可以传结构体中的整数, 这需要根据具体接口的要求正确使用.

struct in_addr { 
in_addr_t s_addr; /* 32-bit IPv4 address */ 
                 /* network byte ordered */ 
};
sockaddr_in

这个是一个常见的IPV4地址结构, 注释中给出了各个字段的含义与大小. 其中sin_family, sin_port, 以及sin_addr是POSIX规范要求的三个字段, 其他的为额外添加字段. 在POSIX类型中, in_addr_t必须至少是一个32位无符号整数, in_port_t至少是一个16位无符号整数类型, sa_family_t则可以是任意无符合整数类型.

可以看到, POSIX定义了规范定义了各个结构必须有的字段, 以及字段的大小.

struct sockaddr_in {
 uint8_t sin_len; /* length of structure (16) */
 sa_family_t sin_family; /* AF_INET */
 in_port_t sin_port; /* 16-bit TCP or UDP port number */
 /* network byte ordered */
 struct in_addr sin_addr; /* 32-bit IPv4 address */
 /* network byte ordered */
 char sin_zero[8]; /* unused */
};
sockaddr

通用套接字结构, 起来void*的作用, 在定义这个结构之前, ANSI C还没有出来, 还没有void*, 这个结构是为了能够处理任意格式的地址参数, 通过指针的方式来传递, 对于socket编程而言, 地址结构作为参数传递的时候一般是通过指针进行的, 而不是直接传递结构体. 结构体在本机内部使用, 而不会在机器直接传递.有了这个结构体, 在接口编写的时候, 要求的参数是struct sockaddr*类型, 到了函数内部通过类型转换变成具体的地址结构类型.

struct sockaddr {
 uint8_t sa_len;
 sa_family_t sa_family; /* address family: AF_xxx value */
 char sa_data[14]; /* protocol-specific address */
};

IPV6地址结构

in6_addr

这个结构使用128bit的空间直接存储一个ipv6的地址.

struct in6_addr {
 uint8_t s6_addr[16]; /* 128-bit IPv6 address */
 /* network byte ordered */
};
sockaddr_in6

实际使用的IPV6地址.

#define SIN6_LEN /* required for compile-time tests */
struct sockaddr_in6 {
 uint8_t sin6_len; /* length of this struct (28) */
 sa_family_t sin6_family; /* AF_INET6 */
 in_port_t sin6_port; /* transport layer port# */
 /* network byte ordered */
 uint32_t sin6_flowinfo; /* flow information, undefined */
 struct in6_addr sin6_addr; /* IPv6 address */
 /* network byte ordered */
 uint32_t sin6_scope_id; /* set of interfaces for a scope */
};
sockaddr_storage

这个结构和sockaddr的区别在于, 足够大, 能够存储任何系统支持的地址结构,且满足任意的对齐要求, 使用的时候, 需要强制类型转化到特定需要的地址结构. 也是通过传指针的方式来使用的.

struct sockaddr_storage {
 uint8_t ss_len; /* length of this struct (implementation dependent) */
 sa_family_t ss_family; /* address family: AF_xxx value */
 /* implementation-dependent elements to provide:
 * a) alignment sufficient to fulfill the alignment requirements of
 * all socket address types that the system supports.
 * b) enough storage to hold any type of socket address that the
 * system supports.
 */
};
addrinfo

这个结构可以通过函数getaddrinfo来获取,一方面可以作为getaddrinfo函数调用时候的过滤器, 另一方面可以装getaddrinfo返回的结果(通过参数列表中的指针返回). 可以看到, 其是一个链表结构, 其结构成员如下.

struct addrinfo {
    int ai_flags; // AI_PASSIVE, AI_CANONNAME, etc.
    int ai_family; // AF_INET, AF_INET6, AF_UNSPEC
    int ai_socktype; // SOCK_STREAM, SOCK_DGRAM
    int ai_protocol; // use 0 for "any"
    size_t ai_addrlen; // size of ai_addr in bytes
    struct sockaddr *ai_addr; // struct sockaddr_in or _in6
    char *ai_canonname; // full canonical hostname
    struct addrinfo *ai_next; // linked list, next node
};

我们接下来通过getadd

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值