zoukankan      html  css  js  c++  java
  • 2. socket结构体——表示socket地址

    一、两种通用socket结构体

    1. sockaddr

    struct sockaddr {
    	sa_family_t	sa_family;			// 地址族 
    	char		sa_data[14];		// 存放socket地址值 
    };

    补:由于不同的协议栈的地址值具有不同的含义和长度(如PF_INET6的地址值占用26字节,更不必说PF_UNIX的地址值最大可达到108字节),所以14字节的sa_data根本无法容纳多数协议族的地址值。

    2. sockaddr_storage

    struct sockaddr_storage {
    	sa_family_t			sa_family;								// 地址族 
    	unsigned long int 	__ss_align;								// 用于内存对齐 
    	char				__ss_padding[128-sizeof(__ss_align)];  	// 提供足够大的空间用于存放地址值 
    };
    

    这两个通用socket地址结构体显然很不好用,比如设置与获取IP地址和端口号就需要执行繁琐的位操作。所以,Linux为各个协议族提供了专门的socket地址结构体。

    二、专用socket结构体

    1. sockaddr_in

    struct sockaddr_in {
    	sa_family_t 	sin_family;		// 地址族 
    	u_int16_t		sin_port;		// 端口号 
    	struct in_addr	sin_addr;		// IPv4地址结构体 
    }; 
    
    struct in_addr {
    	u_int32_t		s_addr;			// IPv4地址 
    };

    2. sockaddr_in6

    struct sockaddr_in6 {
    	sa_family_t 	sin6_family;	// 地址族 
    	u_int16_t		sin6_port;		// 端口号 
    	struct in6_addr	sin6_addr;		// IPv6地址结构体 
    	u_int32_t		sin6_flowinfo;	// 流信息 
    	u_int32_t		sin6_scope_id;	// scope ID 
    }; 
    
    struct in6_addr {
    	unsigned char 	sa_addr[16];	// IPv6地址 
    };
    

      

    3. sockaddr_un

    struct sockaddr_un {
    	sa_family_t		sin_family;		// 地址族 
    	char			sun_path[108];	// 文件路径名 
    };
    

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

    三、余音绕梁

    1. socket地址结构体大小的数据类型为:socklen_t

    typedef uint32_t socklen_t;
    

    2. 为何socket编程接口使用的地址参数的类型是sockaddr?

    因为socket编程接口需要处理sockaddr_in、sockaddr_in6、sockaddr_un等socket地址结构,为了满足这些需求,于是socket编程接口中的指针参数便指向通用socket地址结构。言下之意就是,我们只需知道sockaddr存在的唯一用途就是对指向特定于协议的socket地址结构体的指针执行强制类型转换。

    3. sockaddr_storage结构体往往用于事先不知道地址族的类型这一情况

    /* 获取socket的地址族 */
    int getFamily(int fd)
    {
    	struct sockaddr_storage ss;
    	socklen_t len = sizeof(ss);
    	getsockname(fd, (struct sockaddr*)&ss, &len);
    	return ss.sa_family;
    }
    

    补:既然事先不知道要分配的socket地址结构体的类型,我们只能采用sockaddr_storage这个通用socket地址结构体,因为它能够承载系统支持的任何socket地址结构体。也就是说,它能够容纳下sockaddr_in6结构体的26字节的地址值,也能够容纳下sockaddr_un结构体的108字节的文件路径名。  

      

      

      

  • 相关阅读:
    面试题11:旋转数组的最小数字(C++)
    2019.9.20学习内容及随堂笔记
    2019.9.19学习内容及小结
    2019.9.18(day39)学习内容及小结
    2019.9.17学习内容及随堂笔记
    2019.9.16学习内容及随堂笔记
    2019.9.12(day36)学习内容及笔记
    2019.9.11学习内容及随堂笔记
    2019.9.10学习内容及随堂笔记
    2019.9.9学习内容及随堂笔记
  • 原文地址:https://www.cnblogs.com/xzxl/p/9560969.html
Copyright © 2011-2022 走看看