`

IPv4 和 IPv6 的套接字地址结构

阅读更多
    大多数套接字函数都需要一个指向套接字地址结构的指针作为参数,每个协议族都定义有它自己的套接字地址结构。这些结构的名字均以“sockaddr_”开头,并以对应每个协议准的唯一后缀结尾。
    IPv4 套接字地址结构通常也称为“网际套接字地址结构”,它以“sockaddr_in”命名,定义在 <netinet/in.h> 头文件中。下面是它的 POSIX 定义。
#include <netinet/in.h>

struct in_addr{
    in_addr_t    s_addr;          // 32-bit IPv4 address, network byte ordered
    /* 其它大多历史字段现已经被废除 */
};

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
};

    根据该定义,需要对套接字地址结构做几点一般性的说明。
    1、长度字段 sin_len 是为增加对 OSI 协议的支持而随 4.3 BSD-Remo 添加的。正是因为有了该字段,才简化了长度可变套接字地址结构的处理。并非所有的厂家都支持该字段,而且 POSIX 规范也不要求有这个成员。
    2、即使有长度字段,我们也无需设置和检查它(除非涉及路由套接字),它是由处理来自不同协议族的套接字地址结构的例程(如路由表处理代码)在内核中使用的(在源自 Berkeley 的实现中,从进程到内核传递套接字地址结构的 4 个套接字函数(bind、connect、sendto 和 sendmsg)都要调用 sockargs 函数,该函数从进程复制套接字地址结构,并显示地把它的 sin_len 字段设置成早先作为参数传递给这 4 个函数的该地址结构的长度。从内核到进程传递套接字地址结构的 5 个套接字函数(accept、recvfrom、recvmsg、getpeername 和 getsockname)均在返回到进程之前设置 sin_len 字段)。
    3、POSIX 规范只需要这个结构中的 3 个字段:sin_family、sin_port 和 sin_addr。对于符合 POSIX 的实现来说,定义额外的结构字段是可以接受的。另外,几乎所有的实现都增加了 sin_zero 字段,所以所有的套接字地址结构大小都至少是 16 字节。
    4、在字段 s_addr、sin_family 和 sin_port 的 POSIX 数据类型中,in_addr_t 数据类型必须是一个至少 32 位的无符号整数类型,in_port_t 必须是一个至少 16 位的无符号整数类型,而 sa_family_t 可以是任何无符号整数类型。在支持长度字段的实现中,sa_family_t 通常是一个 8 位的无符号整数,而在不支持长度字段的实现中,它则是一个 16 位的无符号整数。下表列出了 POSIX 定义中常用的这种数据类型。

    5、套接字地址结构仅在给定主机上使用:虽然结构中的 IP 地址和端口号等字段用在不同主机之间的通信中,但是结构本身并不在主机之间传递。
    当作为任何套接字函数的参数时,套接字地址结构总是以引用形式来传递,所以这就要求对应的套接字函数必须处理来自所支持的任何协议族的套接字地址结构。为解决如何声明所传递的指针的数据类型这一问题,在 ANSI C 定义之前(那时还没有“void *”这一通用的指针类型)所采取的办法是定义一个如下的通用套接字地址结构。
#include <sys/socket.h>

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

    于是套接字函数就被定义成如下形式:
        int bind(int, struct sockaddr *, socklen_t);
    这就要求在将指向特定于协议的套接字地址结构的指针传递给任何的套接字函数之前都要进行强制类型转换。比如:
            struct sockaddr_in serv;      // IPv4 socket address structure.
            /* fill in serv() */
            bind(sockfd, (struct sockaddr *)&serv, sizeof(serv));
    从内核的角度看,使用指向通用套接字地址结构的指针另有原因:内核必须取调用者的指针,把它转换成“struct sockaddr *”类型,然后检查其中 sa_family 字段的值来确定该结构的真实类型。而从应用程序开发人员的角度来看,这些通用套接字地址结构的唯一用途就是对指向特定于协议的套接字地址机构的指针执行强制类型转换。要是“void *”指针类型可用就更简单了,因为无须显示进行类型转换。
   
    说完 IPv4 套接字地址结构,现在说说 IPv6 套接字地址结构。
#include <netinet/in.h>

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

#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
};

    这里需要注意以下几点:
    1、如果系统支持套接字地址结构中的长度字段,那么 SIN6_LEN 常量必须定义。
    2、IPv6 的地址族是 AF_INET6,而 IPv4 的是 AF_INET。
    3、结构中字段的先后顺序做过编排,使得如果 sockaddr_in6 的结构本身是 64 位 对齐的,那么 128 位的 sin6_addr 字段也是 64 位对齐的。
    4、sin6_flowinfo 字段分成两部分:a) 低序 20 位是流标(flow label);b) 高序 12 位保留。
    5、对于具备范围的地址,sin6_scope_id 字段标识其范围。最常见的是链路局部地址的接口索引。
    IPv6 套接字 API 中定义了一种新的通用套接字地址结构 sockaddr_storage,它克服了现有“struct sockaddr”的一些缺点,足以容纳系统所支持的任何套接字地址结构。
#include <netinet/in.h>

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 fullfill 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.
  */
};

    sockaddr_storage 同 sockaddr 通用套接字地址结构的差别:
    1、如果系统支持的任何套接字地址结构有对齐要求,那么 sockaddr_storage 能够满足最苛刻的对齐要求。
    2、sockaddr_storage 足够大,能容纳系统支持的任何套接字地址结构。
    注意,除 ss_family 和 ss_len(如果有的话)外,sockaddr_storage 结构中的其他字段对用户来说都是透明的。sockaddr_storage 结构必须类型强制转换成或复制到适合于 ss_family 字段所给出地址类型的套接字地址结构中,才能访问其他字段。
  • 大小: 38.3 KB
分享到:
评论

相关推荐

    IPV4和IPV6兼容的socket编程(原著)

    - `sockaddr_storage` 结构体是为兼容IPv4和IPv6设计的,它足够大以容纳任何类型的地址结构。在处理未知地址类型时,可以先将其初始化为`sockaddr_storage`,然后根据需要转换为`sockaddr_in`或`sockaddr_in6`。 ...

    IPV4与IPV6兼容socket编程接口详解[归纳].pdf

    IPV4与IPV6兼容socket编程接口详解 ...IPV4与IPV6兼容的套接字编程接口是指同时支持IPV4和IPV6两种网络协议的套接字编程接口,这种接口能够同时支持ipv4和ipv6两种网络协议,满足了不同网络应用的需求。

    IPV4与IPV6兼容的socket编程

    通过将这三个参数结合起来,应用层就可以和传输层(或网络层)通过套接字接口,区分来自不同应用程序进程或网络连接的通信。 TCP 编程的服务器端和客户端的步骤 -------------------------------- 在讨论 IPV4 和 ...

    支持IPv4和IPv6的TCPserver与client代码

    由于要同时支持IPv4和IPv6,我们需要创建两个socket,分别使用`AF_INET`(IPv4)和`AF_INET6`(IPv6)地址族,并设置相应的套接字选项。接下来,服务器进入循环,等待客户端的连接,并在有新连接时创建一个新的线程...

    ipv6套接字编程ppt

    IPv6套接字地址结构(sockaddr_in6)包括一个128位的IPv6地址、16位的端口号、32位的优先级和流量标记等信息。这使得IPv6能够支持更大的地址空间和更丰富的网络控制功能。 在进行套接字编程时,创建套接字是第一步...

    ipv6 编程指导 从ipv4到ipv6

    总的来说,IPv6套接字编程不仅仅是对IPv4套接字编程的简单扩展,它涉及到了新的数据结构、函数和通信策略。开发者在进行IPv6编程时,必须清楚地理解IPv4和IPv6之间的差异,包括地址格式、协议头结构、以及连接和通信...

    ipv4/ipv6服务器模块

    在服务器编程中,这通常涉及到监听多个套接字,一个用于IPv4(使用`AF_INET`地址族),另一个用于IPv6(使用`AF_INET6`地址族)。服务器会根据客户端的连接请求,选择合适的套接字进行通信。 易语言是一种中文编程...

    基于IPv4_IPv6双协议栈的通信模块及实现

    IPv6套接字地址结构被命名为sockaddr_in6,其中包含128位的IPv6地址,以及传输层端口号、套接字类型等信息。 #### IPv6的Socket API函数 IPv6的Socket API函数在很大程度上继承了IPv4的API,但为了适应IPv6的特性...

    支持IPv4和IPv6双协议的文件传输工具

    本软件同时支持IPv4和IPv6协议,只要双方主机有一种协议可接入网络即可 2.双击处于Running 状态的任务,可以停止任务,注意本软件暂不支持断点续传,停止后此次任务将失败 3.支持文件鼠标拖拽 4.暂不支持文件夹...

    IPV4与IPV6兼容的socket编程[归纳].pdf

    4. IPv4和IPv6的差异:IPv4和IPv6是两个不同的网络协议,具有不同的地址长度和地址格式。IPv4地址长度为32位,IPv6地址长度为128位。Socket编程需要兼容这两种协议,以确保网络通信的可靠性和稳定性。 5. Socket...

    cpp-将只有ipv4的地址转换为ipv6支持地址

    1. **socket编程**:C语言提供了套接字API,如`socket()`、`bind()`、`connect()`和`listen()`等,用于创建和管理网络连接。在处理IPv4和IPv6时,需要使用`AF_INET`和`AF_INET6`作为地址族。 2. **struct sockaddr_...

    基于IPV4/IPV6的流媒体内容分发网络研究

    - 使用封装类实现网络通信模块的功能,包括`IPAddress`类处理套接字地址,异常处理类管理Socket异常,以及网络通信类提供TCP、多线程和多路复用等功能。 - 下载并集成IPv6支持补丁,主要包括`tpipv6.h`和`wspiapi....

    linux 套接字 socket 函数 手册

    本文档是 Linux 套接字 Socket 编程手册,涵盖了 Socket 编程的各个方面,包括套接字函数、字节操作函数、IPv4 地址转换函数、IPv4、IPv6 通用地址转换函数和 TCP 套接口函数等。 套接字函数 套接字函数是 Socket ...

    UDP UDP广播的实现IPv4&IPv6

    1. 创建套接字:在C/C++中,使用`socket()`函数创建一个UDP套接字,指定协议族为AF_INET(IPv4)或AF_INET6(IPv6),类型为SOCK_DGRAM(UDP)。 2. 设置广播选项:使用`setsockopt()`函数,设置套接字选项`SO_...

    ipv6_ipv4_IOCP.zip

    这通常涉及到使用套接字API的特定功能,如`AF_INET6`地址族,以及`getaddrinfo`和`getnameinfo`等函数来处理地址转换和解析,确保代码能够正确处理IPv4和IPv6地址。 IOCP(I/O完成端口)是Windows操作系统中的一个...

    易语言取封包套接字IP端口模块

    在这个特定的案例中,"易语言取封包套接字IP端口模块"是一个专门用于处理网络封包,获取其中的IP地址和端口号的工具。 封包在网络通信中扮演着数据载体的角色,它包含有源地址、目标地址、端口号以及数据本身。IP...

    Java 套接字编程Java 套接字编程

    Java支持两种主要类型的套接字:流套接字(`Socket`)和自寻址数据套接字(`DatagramSocket`)。 - **流套接字**:流套接字提供了一种可靠的、面向连接的服务,它基于TCP协议工作。流套接字适用于需要保证数据完整...

    利用套接字获取主机的IP地址

    总结起来,利用套接字获取主机IP地址是一项基础的网络编程任务,它可以帮助开发者更好地理解和管理网络环境。在多网卡环境下,这项能力尤为重要,因为它可以揭示主机在网络中的全部身份。通过学习和实践这样的实例,...

    易语言枚举套接字与发送封包

    易语言是中国自主研发的一种简单易学的编程语言,它为开发者提供了便捷的方式来处理网络通信问题,如枚举套接字和发送封包。下面将详细阐述这两个关键概念。 1. 枚举套接字(Enumerating Sockets) 枚举套接字是指...

    IPV6测试,实现IPV6的套接口编程

    通过分析和学习这段代码,开发者可以更好地理解和掌握IPv6套接字编程,这对于构建支持IPv6的网络应用至关重要。 总的来说,IPv6套接口编程涉及到对IPv6地址的处理、套接字的创建和管理,以及网络通信的实现。通过...

Global site tag (gtag.js) - Google Analytics