socket 接口

更新时间:
2024-03-14
下载文档

socket 接口

在很多底层网络应用开发者的眼里,一切编程都是 socket(套接字),几乎所有的网络编程都要依靠 socket。我们每天打开浏览器浏览网页时,浏览器进程和 Web 服务器之间都需要 socket 来进行通信。socket 是网络通信中应用程序对应的进程和网络协议之间的接口,如下图所示。

socket 在网络传输中有如下作用:

  • socket 位于协议之上,屏蔽了不同网络协议之间的差异:。
  • socket 是网络编程的入口,它提供了大量的系统调用,构成了网络程序的主体。
  • socket 是 SylixOS 文件系统中的一个设备,可以通过标准 I/O 函数对 socket 进行操作,这使得我们对网络的控制和对文件的控制一样方便。

常用的 socket 类型有三种:流式(SOCK_STREAM)、数据报式(SOCK_DGRAM)以及原始式(SOCK_RAW)。流式 socket 是一种面向连接的 socket,针对于面向连接的 TCP 服务应用;数据报式 socket 是一种无连接的 socket,对应于无连接的 UDP 服务应用,对于 TCP 或 UDP 的程序开发,焦点在 Data 字段,我们没法直接对 TCP 或 UDP 头部字段进行修改,当然还有 IP 头。换句话说,我们对它们头部操作的空间非常受限,只能使用它们已经开放给我们的诸如源/目的 IP,源/目的端口等;原始式 socket 可以得到原始的 IP 包,可以自定义 IP 所承载的具体协议类型,如 TCP,UDP 或 ICMP,并手动对每种承载在 IP 协议之上的报文进行填充。

IP 地址和端口号唯一标识网络通信中的一个应用程序,其中 IP 地址加端口号就称之为 socket,也被称之为套接字。为 TCP/IP 协议设计的应用层编程接口称为 socket API。socket API 在网络分层结构中的位置,如下图所示。

网路字节序

我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分,磁盘文件中的多字节数据相对于文件中的偏移地址也有大端和小端之分。网络数据流同样有大端和小端之分,如何定义网络数据流的地址是一个需要关注的话题,发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出,接收主机把从网络上接收到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存,因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址。

16 位数据大小端表示与内存布局,如下图所示。

TCP/IP 协议规定,网络数据流应采用大端字节序,即低地址存放高字节。为使网络程序具有可移植性,使同样的 C 代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。

#include <arpa/inet.h>
uint32_t htonl(uint32_t x);
uint16_t htons(uint16_t x);
uint32_t ntohl(uint32_t x);
uint16_t ntohs(uint16_t x);

上述函数名字中,h 表示 host,n 表示 network,l 表示 long,s 表示 short。例如 htonl 函数表示将长整数从主机字节序转换为网络字节序并返回。例如,将 IP 地址转换后进行发送,如果主机是小端字节序,这些函数将对参数做相应的大小端转换,然后返回。如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。虽然在使用这些函数时包含的是 <arpa/inet.h> 头文件,但系统实现经常是在其他头文件中声明这些函数,只是这些头文件都包含在 <arpa/inet.h> 中,对于系统来说,这些函数也可被实现为宏。

socket 地址

socket API 适用于各种底层网络协议,如 IPv4、IPv6 以及后面要讲的 UNIX Domain socket。然而,各种网络协议的地址格式并不相同,为使不同格式地址能够传入到套接字函数,地址会被强制转换成一个通用的地址结构 sockaddr。

下面是在 SylixOS 下的实现:

struct sockaddr {
  u8_t           sa_len;
  sa_family_t    sa_family;
#if LWIP_IPV6
  char           sa_data[26];/* sylixos add 4 bytes to a same size with in6 */
#else   /* LWIP_IPV6 */
  char           sa_data[14];
#endif  /* LWIP_IPV6 */
};

IPv4(AF_INET)地址 in_addr 结构:

struct in_addr {
  in_addr_t      s_addr;
};

IPv4(AF_INET)地址 sockaddr_in 结构:

struct sockaddr_in {
  u8_t              sin_len;
  sa_family_t       sin_family;
  in_port_t         sin_port;
  struct in_addr    sin_addr;
#define SIN_ZERO_LEN 8
  char              sin_zero[SIN_ZERO_LEN];
};

下面是 sockaddr_in 结构成员含义:

  • sin_len:数据结构长度,是为增加 OSI 协议支持而增加的,有了长度成员后简化了变长套接口地址结构的处理。
  • sin_family:地址族(AF_INET)。
  • sin_port:网络协议端口号。
  • sin_addr:网路字节序的 IPv4 地址。
  • sin_zero:8 字节的数据填充。

IPv6(AF_INET6)地址 in6_addr 结构:

struct in6_addr {
  union {
    u8_t      u8_addr[16];
    u32_t     u32_addr[4];
  } un;
#define s6_addr  un.u8_addr
};

IPv6(AF_INET6)地址 sockaddr_in6 结构:

struct sockaddr_in6 {
  u8_t               sin6_len;              /* length of this structure             */
  sa_family_t        sin6_family;           /* AF_INET6                             */
  in_port_t          sin6_port;             /* Transport layer port                 */
  u32_t              sin6_flowinfo;         /* IPv6 flow information                */
  struct in6_addr    sin6_addr;             /* IPv6 address                         */
  /*
   * sylixos add this
   */
  u32_t               sin6_scope_id;        /* set of interfaces for a scope        */
};

下面是 sockaddr_in6 结构成员含义:

  • sin6_len:数据结构长度。
  • sin6_family:地址族(AF_INET6)。
  • sin6_port:传输层端口号。
  • sin6_flowinfo:流信息,低序 20 位是流标签,高序 12 位保留。
  • sin6_addr:IPv6 地址。
  • sin6_scope_id:范围 ID。

UNIX 协议域地址 sockaddr_un 结构:

struct    sockaddr_un {
    uint8_t     sun_len;                  /* sockaddr len including null           */
    uint8_t     sun_family;               /* AF_UNIX                               */
    char        sun_path[104];            /* path name (gag)                       */
};

下面是 sockaddr_un 结构成员含义:

  • sun_len:数据结构长度。
  • sun_family:地址族(AF_UNIX)。
  • sun_path:路径名。

不同套接口地址结构对比,如下图所示。

sockaddr_in 中的成员 sin_addr 表示 32 位的 IPv4 地址。但是我们通常用点分十进制的字符串表示 IPv4 地址,以下函数可以在字符串表示和 in_addr 表示之间进行地址转换。

点分十进制字符串(如“192.168.1.15”)转换为 32 位网络字节序二进制值函数:

#include <arpa/inet.h>
uint32_t inet_addr(const char *name);

函数 inet_addr 原型分析:

  • 此函数成功时返回 32 位二进制的网络字节序地址,失败返回 INADDR_NONE。
  • 参数 name 是点分十进制地址,如“192.168.1.15”。

此函数存在一个问题,不能表示全部的有效 IP 地址(从 0.0.0.0 到 255.255.255.255),当函数出错时返回值为 INADDR_NONE(一般为一个 32 位均为 1 的值),这就意味着点分十进制数串 255.255.255.255(这是 IPv4 的有限广播地址)不能由此函数进行转换,因为它的二进制值被用来指示函数失败,此函数还有一个潜在的问题,有些非正式的文档把出错时的返回值定义为-1 而不是 INADDR_NONE,这样比较函数的返回值(无符号的值)与负常值时可能会出问题,这取决于 C 编译器。

点分十进制字符串(如“192.168.1.15”)转换为 32 位网络字节序二进制值函数:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int  inet_aton(const char *name, struct in_addr *addr);

函数 inet_aton 原型分析:

  • 此函数字符串有效时返回 1,无效时返回 0。
  • 参数 name 是点分十进制地址,如“192.168.1.15”。
  • 参数 addr 是用于保存网络字节序二进制值的缓冲地址。

此函数有一个没有写到正式文档中的特征,如果指针为空,则函数仍然执行输入串的有效性检测,但不存储任何结果。

32 位网络字节序二进制值转换为点分十进制字符串(如“192.168.1.15”)函数:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
char *inet_ntoa(struct in_addr addr);

函数 inet_ntoa 原型分析:

  • 此函数正确时返回字符串指针,错误时返回 NULL。
  • 参数 addr 是 32 位网络字节序地址。

由于此函数返回值所指的字符串驻留在静态内存中,这意味着此函数是不可重入的,并且此函数以结构体为参数,而不是指向结构的指针,通常情况,这个函数被设计成宏。

可重入的 32 位网络字节序二进制值转换为点分十进制字符串(如“192.168.1.15”)函数:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
char *inet_ntoa_r(struct in_addr addr, char *buf, int buflen);

函数 inet_ntoa_r 原型分析:

  • 此函数正确时返回字符串指针,错误时返回 NULL。
  • 参数 addr 是 32 位网络字节序地址。
  • 参数 buf 为点分十进制字符串缓冲区。
  • 参数 buflen 为缓冲区长度。

inet_pton 和 inet_ntop 是两个较新的地址转换函数,对 IPv4 和 IPv6 地址都能处理。其中字母 p 和 n 分别代表 presentation 和 numeric。地址表达式(presentation)格式通常是 ASCII 串,数值(numeric)格式是存在于套接口地址结构中的二进制值。

函数 inet_pton 将字符串地址表达式转换为二进制数值:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int  inet_pton(int af, const char *cp, void *buf);

函数 inet_pton 原型分析:

  • 此函数正确时返回 1,错误时返回-1,输入不是有效的表达格式时返回 0。
  • 参数 af 必须是 AF_INET 或者 AF_INET6。其他地址族不被支持,且返回错误。
  • 参数 cp 是地址串,如 IPv4 的“192.168.1.15”。
  • 参数 buf 用于保存二进制结果。

inet_pton 函数没有指定 buf 的大小,因此需要应用程序保证在 AF_INET 时有足够的空间存放一个 32 位地址,在 AF_INET6 时有足够的空间存放一个 128 位地址。

inet_ntop 函数将二进制数值转换为字符串表达式:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
const char *inet_ntop(int af, const void *cp, char *buf, size_t len);

函数 inet_ntop 原型分析:

  • 此函数正确时返回地址串的指针,错误时返回 NULL。
  • 参数 af 必须是 AF_INET 或者 AF_INET6。其他地址族不被支持,且返回错误。
  • 参数 cp 保存了二进制数值。
  • 参数 buf 用于保存转换后的地址字符串。
  • 参数 len 指定了 buf 的大小,用于避免缓冲区的溢出。

地址转换函数总结,如下图所示。

socket 函数

为了执行网络I/O,必须做的第一件事情就是调用 socket 函数,指定期望的通信协议类型(例如:可以指定IPv4 的 TCP通信、指定IPv6 的 UDP通信、指定UNIX 域通信等)。

调用 socket 函数可以创建一个套接字:

#include <sys/socket.h>
int  socket(int domain, int type, int protocol);

函数 socket 原型分析:

  • 此函数成功时返回文件描述符也称之为套接口描述字(socket descriptor),简称为套接字(socketfd),失败时返回-1 并设置错误号。
  • 参数 domain 是协议域,又称协议族。协议族决定了 socket 的地址类型,在通信中必须采用对应的地址,如 AF_INET 决定了要用 IPv4 地址(32 位的)与端口号(16 位的)的组合、AF_UNIX 决定了要用一个绝对路径名作为地址。协议族参数描述,如下表所示。
协议域说明
AF_UNSPEC未指定
AF_INETIPv4 因特网域
AF_INET6IPv6 因特网域
AF_UNIX/AF_LOCALUNIX 域
AF_PACKETPACKET 域
AF_ROUTE路由域
  • 参数 type 是 socket(套接字)类型。如下表所示是 SylixOS 支持的所有类型,当然这些需要搭配具体协议域进行使用。
套接字类型说明
SOCK_DGRAM数据报套接口,固定长度,无连接的,不可靠的报文传递
SOCK_RAW原始套接口,IP 协议的数据报接口
SOCK_SEQPACKET有序分组套接口,固定长度的、有序的、可靠的、面向连接的报文传递
SOCK_STREAM字节流套接口,有序的、可靠的、双向的、面向连接的字节流
  • 参数 protocol 是协议类型:。
协议类型说明
IPPROTO_IPIPv4 网络协议
IPPROTO_ICMP因特网控制报文协议
IPPROTO_TCP传输控制协议
IPPROTO_UDP用户数据报协议
IPPROTO_IPV6IPv6 网络协议
IPPROTO_ICMPV6因特网控制报文协议
IPPROTO_SCTP流控制传输协议
IPPROTO_RAW原始 IP 数据包协议
IPPROTO_UDPLITEUDP传输协议扩展

参数 domain 确定了通信的特性,包括地址格式等。AF_UNIX 是一种高级的 IPC 机制,具体使用将在“AF_UNIX域协议”节中详细叙述,AF_PACKET 是一个较新的套接口类型,支持对数据链路层的操作,具体使用将在“AF_PACKET链路层通信”节中详细叙述。AF_UNSPEC 域在 SylixOS 中不被支持。

参数 protocol 通常为 0,表示为给定的域和套接字类型选择默认协议。当对同一域和套接字类型支持多个协议时,可以使用 protocol 选择一个特定协议。在 AF_INET 通信域中,套接字类型 SOCK_STREAM 的默认协议是传输控制协议(TCP),套接字类型 SOCK_DGRAM 的默认协议是 UDP。

对于数据报接口,两个对等应用程序之间通信时不需要逻辑连接。只需要向对等应用程序所使用的套接字送出一个报文。因此数据报(SOCK_DGRAM)提供了一个无连接的服务。而字节流(SOCK_STREAM)要求在交换数据之前,在本地套接字和通信的对等应用程序的套接字之间建立一个逻辑连接。

对于字节流(SOCK_STREAM),应用程序分辨不出报文的界限。这意味着从字节流套接字读数据时,它也许不会返回所有由发送应用程序所写的字节数。最终可以获得发送过来的所有数据,但也许要通过若干次函数调用才能得到。

并非所有的套接字协议域与类型的组合都是有效的,如下表所示给出了一些有效的组合和对应的真正协议,其中标识为“Y”的项表示是有效的,只是没有找到便捷的缩略词,而标识为“N”的项表示不支持。

类型AF_INETAF_INET6AF_UNIXAF_PACKETAF_ROUTE
SOCK_SEQPACKETSCTPSCTPYNN
SOCK_STREAMTCPTCPYNN
SOCK_DGRAMUDPUDPYYN
SOCK_RAWIPv4IPv6NYY

socket 选项

套接字选项通过调用 setsockopt 函数和 getsockopt 函数进行操作,SylixOS 网络支持多种套接字选项如下表所示。

#include <sys/socket.h>
int  setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);

函数 setsockopt 原型分析:

  • 此函数成功时返回 0,失败时返回-1 并设置错误号。
  • 参数 s 是套接字(socket 函数返回)。
  • 参数 level 是选项等级如下表所示。
  • 参数 optname 是选项名如下表所示。
  • 参数 optval 是选项值。
  • 参数 optlen 是选项长度。

通过调用 setsockopt 函数来设置不同选项等级的不同选项,参数 optval 是一个指向变量的指针类型,根据不同的选项,类型也不同如下表所示。

#include <sys/socket.h>
int  getsockopt(int s, int level, int optname, 
void *optval, socklen_t *optlen);

函数 getsockopt 原型分析:

  • 此函数成功返回 0,失败返回-1 并设置错误号。
  • 参数 s 是套接字(socket 函数返回)。
  • 参数 level 是选项等级如下表所示。
  • 参数 optname 是选项名如下表所示。
  • 输出参数 optval 返回选项值。
  • 参数 optlen 是选项长度。

调用 getsockopt 函数可以获得套接字的选项值,参数 optlen 将返回选项值的实际长度。

选项等级选项名说明适用函数数据类型协议域
SOL_SOCKET
SO_BROADCAST运行发送广播数据报getsockopt
setsockopt
intAF_NET
AF_INET6
SO_ERROR获取待处理错误并消除getsockoptintAF_INET
AF_INET6
AF_ROUTE
AF_UNIX
AF_PACKET
AF_SCTP
SO_KEEPALIVE周期性测试连接是否存活getsockopt
setsockopt
intAF_NET
AF_INET6
SO_LINGER设置socket链接关闭时间,该关闭socket不再进行正常的四次挥手动作getsockopt
setsockopt
struct linger
AF_NET
AF_INET6
AF_UNIX
SO_DONTLINGER关闭SO_LINGER选项setsockoptintAF_UNIX
SO_RCVBUF接受缓冲区大小getsockopt
setsockopt
intAF_NET
AF_INET6
AF_UNIX
AF_PACKET
SO_RCVTIMEO数据接受超时时间getsockopt
setsockopt
struct timeval/ int
AF_NET
AF_INET6
AF_UNIX
AF_PACKET
SO_SNDTIMEO数据发送超时时间getsockopt
setsockopt
struct timeval/ int
AF_NET
AF_INET6
AF_UNIX
SO_REUSEADDR允许重用本地地址getsockopt
setsockopt
intAF_NET
AF_INET6
AF_UNIX
SO_NO_CHECK不创建UDP校验和(该选项不支持 UDPLITE)getsockopt
setsockopt
intAF_NET
AF_INET6
SO_UDPCONALAUDP连接赋值本地地址getsockopt
setsockopt
int
AF_NET
AF_INET6
SO_BINDTODEVICE绑定socket到指定网络接口setsockoptstruct ifreqAF_NET
AF_INET6
SO_SECREGION设置 socket 安全域(仅支持在root权限设置)getsockopt
setsockopt
unsignedintAF_NET
AF_INET6
AF_PACKET
SO_PRIORITY设置IP数据包优先级getsockopt
setsockopt
intAF_NET
AF_INET6
SO_TYPE
获取socket类型(包括:SOCK_RAW/SOCK_STREAM/SOCK_DGRAM)getsockoptint
AF_NET
AF_INET6
AF_UNIX
AF_PACKET
SO_CONTIMEO连接超时时间getsockopt
setsockopt
struct timevalAF_UNIX
SO_PASSCRED是否传输认证信息getsockopt
setsockopt
intAF_UNIX
SO_ACCEPTCONN查看socket是否已经处于listen状态(仅针对getsockopt接口)getsockoptint
AF_NET
AF_INET6
AF_UNIX
SOL_PACKETPACKET_ADD_MEMBERSHIP加入多播组setsockoptstruct packet_mreqAF_PACKET
PACKET_DROP_MEMBERSHIP离开多播组
setsockoptstruct packet_mreqAF_PACKET
PACKET_RECV_OUTPUT
是否接收输出数据包getsockopt
setsockopt
intAF_PACKET
PACKET_RX_RING
为mmap分配内存空间
setsockoptstruct tpacket_reqAF_PACKET
PACKET_VERSION设置AF_PACKET版本getsockopt
setsockopt
enum tpacket_versionsAF_PACKET
PACKET_STATISTICS收集数据包统计信息getsockoptstruct tpacket_statsAF_PACKET
PACKET_HDRLEN数据包头部长度getsockoptintAF_PACKET
PACKET_RESERVE为mmap分配空间保留额外的头部空间getsockopt
setsockopt
unsignedintAF_PACKET
IPPROTO_IPIP_TTLIP包在网络中的存活时间getsockopt
setsockopt
intAF_INET
IP_TOS服务类型和优先级getsockopt
setsockopt
intAF_INET
IP_MINTTL最小 TTL 值getsockopt
setsockopt
intAF_INET
IP_HDRINCL操作系统不自动添加IP头部,由应用程序添加getsockopt
setsockopt
intAF_INET
IP_OPTIONS应用程序添加IP头部自定义选项(仅支持RAW socket 类型)getsockopt
setsockopt
intAF_INET
IP_MULTICAST_TTL多播TTLgetsockopt
setsockopt
intAF_INET
IP_MULTICAST_IF多播数据发送接口配置getsockopt
setsockopt
struct in_addrAF_INET
IP_MULTICAST_LOOP多播数据是否回环本地发送接口getsockopt
setsockopt
intAF_INET
IP_MSFILTER
组播源过滤配置getsockopt
setsockopt
struct ip_msfilterAF_INET
MCAST_MSFILTER组播组过滤配置getsockopt
setsockopt
struct group_filterAF_INET
MRT_VERSION组播路由版本信息setsockoptintAF_INET
MRT_ASSERT组播路由断言setsockoptintAF_INET
MRT_API_SUPPORT组播路由API支持情况setsockoptuint32_tAF_INET
MRT_API_CONFIG组播路由配置情况setsockoptuint32_tAF_INET
IP_PKTINFO启用接收包扩展信息setsockoptintAF_INET
IP_ADD_MEMBERSHIP加入多播组setsockoptstruct ip_mreqAF_INET
IP_DROP_MEMBERSHIP离开多播组setsockoptstruct ip_mreqAF_INET
IP_ADD_SOURCE_MEMBERSHIP加入源特定多播组setsockopt
struct ip_mreq_sourceAF_INET
IP_DROP_SOURCE_MEMBERSHIP离开源特定多播组setsockoptstruct ip_mreq_sourceAF_INET
IP_BLOCK_SOURCE
增加一个被屏蔽的源地址到多播组(可以是全部网络接口)setsockoptstruct ip_mreq_sourceAF_INET
IP_UNBLOCK_SOURCE从多播组解除一个被屏蔽的源地址(可以是全部网络接口)setsockoptstruct ip_mreq_sourceAF_INET
AF_INET
MCAST_JOIN_GROUP加入多播组setsockoptstruct group_reqAF_INET
MCAST_LEAVE_GROUP离开多播组setsockoptstruct group_reqAF_INET
MCAST_JOIN_SOURCE_GROUP加入源多播组setsockoptstruct group_source_reqAF_INET
MCAST_LEAVE_SOURCE_GROUP离开源多播组setsockoptstruct group_source_reqAF_INET
MCAST_BLOCK_SOURCE增加一个被阻止的源地址到多播组(单个网络接口)setsockoptstruct group_source_reqAF_INET
MCAST_UNBLOCK_SOURCE从多播组解除一个被屏蔽的源地址(单个网络接口)setsockoptstruct group_source_reqAF_INET
MRT_INIT初始化组播路由表setsockoptintAF_INET
MRT_DONE完成组播路由配置setsockoptN/AAF_INET
MRT_ADD_VIF添加一个虚拟接口到组播路由接口setsockoptstruct vifctlAF_INET
MRT_DEL_VIF删除一个虚拟接口从组播路由接口setsockoptvifi_tAF_INET
MRT_ADD_MFC添加或更新组播转发缓存(Multicast ForwardingCache,MFC)表项setsockoptstruct mfcctl2AF_INET
MRT_DEL_MFC删除指定的MFC表项setsockoptstruct mfcctl2AF_INET
MRT_ASSERT触发组播路由表中的断言setsockoptintAF_INET
MRT_API_CONFIG组播路由配置情况setsockoptuint32_tAF_INET
IPPROTO_TCPTCP_NODELAY是否开启小包立即发送功能getsockopt
setsockopt
int
AF_INET
AF_INET6
TCP_KEEPALIVE探测对方是否存活前连接闲置秒数getsockopt
setsockopt
intAF_INET
AF_INET6
TCP_KEEPIDLE
对一个连接探测前的允许时间getsockopt
setsockopt
intAF_INET
AF_INET6
TCP_KEEPINTVL
两个探测的时间间隔getsockoptintAF_INET
AF_INET6
TCP_KEEPCNT探测的最大次数getsockoptintAF_INET
AF_INET6
TCP_REALTIMETCP实时模式,快速重传getsockopt
setsockopt
intAF_INET
AF_INET6
TCP_QUICKACK立即发送ACKgetsockopt
setsockopt
int
AF_INET
AF_INET6
TCP_DESC获取TCP状态信息getsockoptstruct tcp_descAF_INET
AF_INET6
IPPROTO_IPV6IPV6_MINHOPCNTIPV6最小TTL值getsockopt
setsockopt
intAF_INET6
IPV6_UNICAST_HOPS单播数据包跳数getsockopt
setsockopt
intAF_INET6
IPV6_MULTICAST_IF设置组播数据包网络接口索引getsockopt
setsockopt
intAF_INET6
IPV6_MULTICAST_HOPS设置组播数据包跳数getsockopt
setsockopt
intAF_INET6
IPV6_MULTICAST_LOOP组播数据包是否回环到发送者getsockopt
setsockopt
intAF_INET6
IPV6_CHECKSUM检验和getsockopt
setsockopt
int
AF_INET6
IPV6_V6ONLY套接字仅支持IPV6getsockopt
setsockopt
intAF_INET6
IPV6_RECVPKTINFO接收附加消息setsockoptintAF_INET6
IPV6_RECVHOPLIMIT接收跳数限制setsockoptintAF_INET6
IPV6_JOIN_GROUP加入IPV6组播组setsockoptstruct ipv6_mreqAF_INET6
IPV6_LEAVE_GROUP离开IPV6组播组setsockoptstruct ipv6_mreqAF_INET6
IPPROTO_UDPLITEUDPLITE_SEND_CSCOV
执行发送校验和
setsockopt
intAF_NET
AF_INET6
UDPLITE_RECV_CSCOV执行接收校验和setsockoptintAF_NET
AF_INET6
IPPROTO_RAWIPV6_CHECKSUM
IPV6校验和
setsockopt
getsockopt
intAF_NET6

表中 SOL_PACKET 选项等级用于 AF_PACKET 类型套接字的选项,这些选项将在“AF_PACKET链路层通信节”中详细介绍。

下面程序展示了通过设置套接字选项来控制相应套接字的行为,此程序首先通过调用 setsockopt 函数设置 IPv4 的接收缓冲区的大小,然后调用 getsockopt 函数来获得接收缓冲区的大小以确认接收缓冲区的大小被正确改变。

#include <stdio.h>
#include <sys/socket.h>
int main (int argc, char *argv[])
{
    int          sockfd;
    int          sopt = 2048;
    int          gopt;
    int          ret;
    socklen_t    len  = sizeof(int);
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        fprintf(stderr, "create socket error.\n");
        return  (-1);
    }
    ret = setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &sopt, len);
    if (ret < 0) {
        fprintf(stderr, "setsockopt error.\n");
        return  (-1);
    }
    ret = getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &gopt, &len);
    if (ret < 0) {
        fprintf(stderr, "getsocket error.\n");
        return  (-1);
    }
    fprintf(stdout, "IPv4 recv buffer size: %d\n", gopt);
    return  (0);
}

在 SylixOS Shell 下运行程序,结果显示如下:

# ./Set_Socket_Options
IPv4 recv buffer size: 2048
文档内容是否对您有所帮助?
有帮助
没帮助