linux socket地址

随笔2周前发布 玉林缘
2 0 0

合集 – 网络编程(16)

1.linux socket地址2023-10-112.linux IP 地址转换2023-10-113.linux TCP 通信流程 套接字函数 socket() bind() listen() accept() connect()2023-10-124.linux TCP通信实现 服务器端 – 客户端2023-10-125.linux TCP 三次握手2023-10-126.linux TCP滑动窗口 四次挥手2023-10-227.linux 多进程实现并发服务器 多线程并发2023-10-248.linux TCP状态转换 半关闭 shutdown netstat 端口复用 setsockopt2023-10-249.linux IO多路复用 select poll epoll2023-10-2510.linux 多路复用—poll2023-10-3011.linux 多路复用—epoll2023-10-3112.linux UDP 通信2023-11-0313.linux 本地套接字通信2023-11-0314.linux Web服务器以及HTTP协议2023-11-0815.linux 服务器编程基本框架和两种高效事件的处理模式2023-11-1016.linux 线程池 EPOLLONESHOT事件2023-11-13

收起

socket地址:

  //socket地址其实是一个结构体,封装端口号和 IP等信息。 后面的 socket 相关的 API 需要使用到这个 socket 地址。 

  //客户端   –>   服务器(IP   、 Port)

通用 socket 地址:

  socket 网络编程接口中表示 socket 地址是结构体 sockaddr,其定义如下:(IPv4使用)

#include <bits/socket.h>
struct sockaddr
{
    sa_family_t sa_family;
    char sa_data[14];
};

typedef unsigned short int sa_family_t;//2个字节

  sa_family 成员是地址族类型(sa_family_t)的变量。地址族类型通常与协议族类型对应。常见的协议族(protocol family,也称 domain)和对应的地址族如下所示:

linux socket地址

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

  sa_data 成员用于存放 socket 地址值。但是,不同的协议族的地址值具有不同的含义和长度,如下所示:

linux socket地址

  由上表可知,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;

但通用的socket地址使用较为不便,因此有了 专用 socket 地址:

  很多网络编程函数诞生早于 IPv4 协议,那时候都使用的是 struct sockaddr 结构体,为了向前兼容, 现在 sockaddr 退化成了 (void*)的作用,传递一个地址给函数

  至于这个函数是 sockadd_in 还是sockaddr_in6,由地址族确定,然后函数内部再强制类型转化为所需的地址类型。    

              linux socket地址

UNIX(了解)本地域协议族使用如下专用的socket地址结构体:

#include <sys/un.h>
struct sockaddr_un
{
    sa_family_t sin_family;
    char sun_path[108];
};

TCP/IP 协议族有  sockaddr_in  和  sockaddr_in6  两个专用的 socket 地址结构体,它们分别用于 IPv4  和  IPv6:

#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;//int类型数据 占4个字节
};

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。       

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...