系统的套接字地址结构体,的协议族类型

linux系统的socket是一个通用的网络编程接口。它支持多种协议。每个协议使用不同的套接字地址结构。为了保持socket函数调用参数的一致性,linux系统定义了一个通用的socket地址结构,在sys/socket.h中定义如下:

结构 osockaddr

{

unsigned short int sa_family;

无符号字符 sa_data[14];

};

这是一个结构,我们用两个元素来看看:

1、 第一个元素sa_family是socket的协议族地址类型,一般格式为AF_XXX。例如linux的通信方式套接字,AF_INET 是 TCP/IP 协议族的地址类型。这个协议族的类型很多,在socket.h中定义,见图1和图2:

图一

图2

2、sa_data 存储特定的协议地址。不同的协议族有不同的地址格式。

socket支持的每个协议族都定义了自己的socket地址结构,以前缀sockaddr开头,TCP/IP协议的socket地址结构为sockaddr_inlinux的通信方式套接字,在头文件netinet/in.h中定义:

/* 互联网地址。 */

typedef uint32_t in_addr_t;

结构 in_addr

{

in_addr_t s_addr;

};

/* IPv6 地址 */

/* IPv6 地址 */

结构 in6_addr

{

联合

{

uint8_t__u6_addr8[16];

uint16_t __u6_addr16[8];

uint32_t __u6_addr32[4];

} __in6_u;

#define s6_addr__in6_u.__u6_addr8

#ifdef __USE_MISC

# 定义 s6_addr16__in6_u.__u6_addr16

# 定义 s6_addr32__in6_u.__u6_addr32

#endif

};

/* 描述 Internet 套接字地址的结构。 */

结构 sockaddr_in

{

__SOCKADDR_COMMON (sin_);

in_port_t sin_port;/* 端口号。 */

struct in_addr sin_addr;/* Internet 地址。 */

/* 填充到 `struct sockaddr’ 的大小。 */

unsigned char sin_zero[sizeof (struct sockaddr) –

__SOCKADDR_COMMON_SIZE –

sizeof (in_port_t) –

sizeof (struct in_addr)];

};

#if !__USE_KERNEL_IPV6_DEFS

/* 同上,对于 IPv6. */

结构 sockaddr_in6

{

__SOCKADDR_COMMON (sin6_);

in_port_t sin6_port;/* 传输层端口# */

uint32_t sin6_flowinfo;/* IPv6流信息*/

struct in6_addr sin6_addr;/* IPv6 地址 */

uint32_t sin6_scope_id;/* IPv6 scope-id */

};

#endif /* !__USE_KERNEL_IPV6_DEFS */

上面的sockaddr_in6就是ipv6的地址结构。现在我们更多地使用ipv4,所以一般使用sockaddr_in。使用这种地址结构时,需要注意以下几点:

1、 sockaddr_in 结构中的 TCP 或 UDP 端口号 sin_port 和 IP 地址 sin_addr 以网络字节顺序存储(这将在下一章解释)。

2、 32 位 IP 地址可以通过两种不同的方式引用。例如:假设变量 servaddr 被定义为一个 Internet 套接字地址结构,那么可以使用 servaddr.sin_addr 或 servaddr.sin_addr.s.addr 来引用这个 ip 地址。需要注意的是,前者指的是结构体类型(struct in_addr)数据,后者指的是整数类型的数据。当使用ip地址作为函数参数时,需要指定使用哪种类型的数据。因此,编译器对结构类型参数和整数类型参数的处理方式不同。

3、 不使用Sin_zero 成员,引入它是为了与通用套接字地址(struct Sockaddr)保持一致。编程中一般设置为0.

4、 套接字地址结构仅被原生 tcp 协议用来记录套接字信息。这个结构体变量本身并不是在网络上传输的,但是它的一些内容比如ip地址和端口号是在网络上传输的,这也是为什么这两部分数据需要转换成网络字节序的原因。

在sockaddr_in结构体中设置ip地址时,需要将字符串形式表示的ip地址转换成二进制形式。在 arpa/inet.h 中,inet_aton、inet_addr 和 inet_ntoa 以数字点的形式定义。字符中的ip地址以32位网络字节序转换为ip地址的二进制形式。

好了,今天就到这里。

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论