4.11、socket地址

1.通用 socket 地址

  • socket 网络编程接口中表示 socket 地址的是结构体 sockaddr,其定义如下:
// socket地址其实是一个结构体,封装端口号和IP等信息。后面的socket相关的api中需要使用到这个socket地址。
// 客户端 -> 服务器(IP, Port)

#include <bits/socket.h>
struct sockaddr {
    
    
	sa_family_t sa_family;
	char sa_data[14];
};
typedef unsigned short int sa_family_t;
  • sa_family 成员是地址族类型(sa_family_t)的变量。地址族类型通常与协议族类型对应。常见的协议族(protocol family,也称 domain)和对应的地址族入下所示:
协议族 地址族 描述
PF_UNIX AF_UNIX UNIX本地域协议族
PF_INET AF_INET TCP/IPv4协议族
PF_INET6 AF_INET6 TCP/IPv6协议族

PF_*AF_* 都定义在bits/socket.h头文件中,且后者与前者有完全相同的值,所以二者通常混用。

  • sa_data 成员用于存放 socket 地址值。但是,不同的协议族的地址值具有不同的含义和长度,如下所示:
协议族 地址值含义和长度
PF_UNIX 文件的路径名,长度可达到108字节
PF_INET 16 bit 端口号和 32 bit IPv4 地址,共 6 字节
PF_INET6 16 bit 端口号,32 bit 流标识,128 bit IPv6 地址,32 bit 范围 ID,共 26 字节
  • 由上表可知,14 字节的 sa_data 根本无法容纳多数协议族的地址值。因此,Linux 定义了下面这个新的通用的 socket 地址结构体,这个结构体不仅提供了足够大的空间用于存放地址值,而且是内存对齐的。
#include <bits/socket.h>
struct sockaddr_storage
{
    
    
	sa_family_t sa_family;
	unsigned long int __ss_align;
	char __ss_padding[ 128 - sizeof(__ss_align) ];
};
typedef unsigned short int sa_family_t;

2.专用socket地址

  • 很多网络编程函数诞生早于 IPv4 协议,那时候都使用的是 struct sockaddr 结构体,为了向前兼容,现在sockaddr 退化成了(void *)的作用,传递一个地址给函数,至于这个函数是 sockaddr_in 还是sockaddr_in6,由地址族确定,然后函数内部再强制类型转化为所需的地址类型。
    在这里插入图片描述
  • UNIX 本地域协议族使用如下专用的 socket 地址结构体:
#include <sys/un.h>
struct sockaddr_un
{
    
    
	sa_family_t sin_family;
	char sun_path[108];
};
  • TCP/IP 协议族有 sockaddr_insockaddr_in6 两个专用的 socket 地址结构体,它们分别用于 IPv4IPv6
#include <netinet/in.h>
struct sockaddr_in
{
    
    
	sa_family_t sin_family; /* __SOCKADDR_COMMON(sin_) */
	in_port_t sin_port; /* Port number. */
	struct in_addr sin_addr; /* Internet address. */
	/* Pad to size of `struct sockaddr'. */
	unsigned char sin_zero[sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE - sizeof (in_port_t) - sizeof (struct in_addr)];
};

struct in_addr
{
    
    
in_addr_t s_addr;
};

struct sockaddr_in6
{
    
    
	sa_family_t sin6_family;
	in_port_t sin6_port; /* Transport layer port # */
	uint32_t sin6_flowinfo; /* IPv6 flow information */
	struct in6_addr sin6_addr; /* IPv6 address */
	uint32_t sin6_scope_id; /* IPv6 scope-id */
};
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef uint16_t in_port_t;
typedef uint32_t in_addr_t;
#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))

所有专用 socket 地址(以及 sockaddr_storage)类型的变量在实际使用时都需要转化为通用 socket 地址类型 sockaddr(强制转化即可),因为所有 socket 编程接口使用的地址参数类型都是 sockaddr

猜你喜欢

转载自blog.csdn.net/z2812470857/article/details/130168688
今日推荐