网络api-套接字选项

概述

获取和设置影响套接字选项方法
a. getsockoptsetsockopt
b. fcntl
c. ioctl

按以下分类介绍:通用,IPv4TCP
fcntl是把套接字设置为非阻塞式I/O型或信号驱动式I/O型及设置套接字属主的POSIX方法

getsockopt和setsockopt函数

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

参数1需指向一个打开的套接字描述符
参数2,类别(通用/IPv4/IPv6/TCP/SCTP/…)
参数4,执行设置/接收,设置值
参数5,参数4指向对象长度

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

套接字选项

如:SO_DEBUG,SO_DONTROUTE,SO_KEEPALIVE,SO_LINGER,SO_OOBINLINE,SO_RCVBUF,SO_RCVLOWAT,SO_SNDBUF,SO_SNDLOWAT,TCP_MAXSEG,TCP_NODELAY

通用套接字选项

由内核中协议无关代码处理

SO_BROADCAST套接字选项

开启或禁止进程发广播消息能力,只有数据报套接字+在支持广播消息网络上(以太网,令牌环网等)才支持广播.
应用进程在发送广播数据报前需设置本套接字选项,故它能防止一个进程在其应用程序没设计成可广播时就发送广播数据报.如目的地址为一个广播地址但广播选项未设置,返回EACCES

SO_DEBUG套接字选项

本选项仅由TCP支持,给一个TCP套接字开启本选项时,内核将为TCP在该套接字发送和接收的所有分组保留详细跟踪信息

SO_DONTROUTE套接字选项

规定外出的分组将绕过底层协议的正常路由机制,路由守护进程经常用本选项来绕过路由表以强制将分组从特定接口送出

SO_ERROR套接字选项

一个套接字上发生错误时,源自Berkeley内核的协议模块将该套接字的名为so_error变量设为标准Unix Exxx中的一个,称其为待处理错误.

内核能以以下方式之一通知进程此错误
(1). 如进程阻塞在对该套接字的select调用上,
无论检查读/写,均返回并设置
(2). 如进程使用信号驱动式I/O模型,则给进程或进程组产生一个SIGIO信号

进程可通过访问SO_ERROR套接字选项获取so_error值,由getsockopt返回的整数值,即为该套接字的待处理错误.so_error随后由内核复位.read时,如无数据可读+出错,返回-1errno被设置,so_error被复位.write时,返回-1errno被设置,so_error被复位.

SO_KEEPALIVE套接字选项

给一个TCP套接字设置保持存活选项后,如两小时内,在该套接字任一方向无数据交换,TCP自动给对端发一个保持存活探测分节,对端必须响应.
(1). 对端以期望的ACK响应
(2). 对端以RST响应,
表示对端已崩溃,套接字待处理错误置为ECONNRESET,套接字关闭
(3). 无响应
再发探测,一段时间后仍无响应,则放弃(认为线路故障).套接字本身被关闭.
如该套接字收到一个ICMP错误作为某个探测分节的响应,则返回相应的错误,套接字关闭.

本选项经常由服务器使用,在其相连客户断线/崩溃时,提供了一种识别方法.以便服务端关闭半开连接.

SO_LINGER套接字选项

#include <sys/socket.h>
struct linger
{
	int l_onoff;
	int l_linger;
};

(1). 如l_onoff0,则关闭本选项.l_linger值被忽略,close立即返回
(2). 如l_onoff为非0,且l_linger0
close某连接时,TCP将中止该连接,即TCP将丢弃保留在套接字发送缓冲区的任何数据,发一个RST给对端
(3). 如l_onoff为非0值且l_linger也为非0
则当套接字关闭时,close阻塞,内核将拖延一段时间,直到
a. 所有数据都已发送完,且均被对方确认
b. 延滞时间到
c. EWOULDBLOCK,发送缓冲区残留数据被丢弃
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
设置SO_LINGER套接字选项后,close的成功返回告诉我们先前发送的数据(和FIN)已由对端TCP确认
不能告诉我们对端应用进程是否已读取数据,如不设该选项,连对端TCP是否确认了数据也不知

shutdown(参数2SHUT_WR)+ read,可让客户知道服务器已读取其数据
在这里插入图片描述

当关闭连接的本地端,根据所调函数(closeshutdown)及是否设置了SO_LINGER
可在3个不同时机返回
a. close立即返回,不等待
b. close拖延到接收了FINACK才返回
c. shutdown+read,等到接收了对端的FIN才返回
获取服务器已读取数据,也可用应用级ACK.服务器每读取客户数据后,发回1字节ACK,客户阻塞读取.
在这里插入图片描述

函数说明
shutdown,SHUT_RD接收缓冲区数据被丢弃,后续接收的数据被丢弃
shutdown,SHUT_WR发送缓冲区内容发到对端,后跟FIN
close,l_onoff=0发送缓冲区内容被发到对端.如描述符引用计数为0,发送FIN,接收缓冲区内容被丢弃.
close,l_onoff=1,l_linger=0发送缓冲区内容被丢弃,如描述符引用计数变为0,发RST.连接状态变为CLOSED.
close,l_onoff=1,l_linger=1发送缓冲区内容被发到对端,如引用计数变为0,发FIN.接收缓冲区内容被丢弃,如在变为CLOSED前延滞时间到,EWOULDBLOCK

通过shutdown可以仅仅关闭发送,仅仅关闭接收.
通过close必然是同时关闭发送和接收.
对发送的关闭,允许立即关闭,延迟关闭.立即关闭的意思是将发送缓存区内容丢弃,且立即发RST给对端.延迟关闭的意思是将发送缓存区现有内容有序发送完毕,再发FIN
对接收的关闭,总是立即的.

SO_OOBINLINE套接字选项

选项开启时,带外数据将被留在正常的输入队列中,此时,接收函数的MSG_OOB标记不能读带外数据

SO_RCVBUF和SO_SNDBUF套接字选项

接收缓冲区被TCP/UDP/SCTP用来保存接收到的数据,直到应用读取.对TCP,套接字接收缓冲区可用空间大小限定了TCP通告对端的窗口大小,流量控制:对端不允许发超过本端通告窗口大小的数据,即使发了超过窗口大小数据,超出部分被丢弃.

设置TCP套接字接收缓冲区大小时,TCP窗口规模选项是在建立连接时用SYN分节与对端互换得到.对客户,SO_RCVBUF选项需在调用connect前设置.对服务器,该选项需在调listen前给监听套接字设置.给已连接套接字设置该选项对可能存在的窗口规模选项无任何影响.

TCP套接字缓冲区大小至少应是相应连接的MSS值的4倍,对单向数据传输,说"套接字缓冲区大小"时,指的是发送端主机上的套接字发送缓冲区大小,和接收端主机上的套接字接收缓冲区大小.

对双向,每端均指接收/发送缓冲区大小,套接字缓冲区中MSS整数倍外的空间不会被使用.
在这里插入图片描述

管道的容量称为带宽-延迟积,将带宽(bit/s)和RTT(秒)相乘,再将结果由位转换为字节计算得到.

SO_RCVLOWAT和SO_SNDLOWAT套接字选项

这两个套接字选项允许我们修改套接字的接收/发送低水位标记,接收低水位标记是让select返回"可读"时套接字接收缓冲区所需的数据量.对TCP/UDP/SCTP,默认为1.发送低水位标记是让select返回"可写"时套接字发送缓冲区所需的可用空间,对TCP,默认值通常为2048

SO_RCVTIMEO和SO_SNDTIMEO套接字选项

允许给套接字的接收和发送设置一个超时值:getsockopt/setsockopt(timeval)
接受超时:read/readv/recv/recvfrom/recvmsg
发送超时:write/writev/send/sendto/sendmsg

SO_REUSEADDR和SO_REUSEPORT套接字选项

SO_REUSEADDR可起到以下4个不同功用
(1). SO_REUSEADDR
允许启动一个监听服务器并捆绑众所周知端口,即使以前建立的将该端口用作它们的本地端口的连接仍存在
发生条件举例:
a. 启动一监听服务器
b. 连接请求到达,派生一个子进程处理此客户
c. 监听服务器终止,子进程继续为现有连接上的客户提供服务
d. 重启监听服务器(采用现有连接上端口)
(2). SO_REUSEADDR
允许在同一端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的本地IP地址

a. 在所有TCP服务器程序中,调bind之前设置SO_REUSEADDR套接字选项
b. 编写一个可在同一时刻在同一主机上运行多次的多播应用时,设置SO_REUSEADDR套接字选项,将所参加多播组的地址作为本地IP地址捆绑

SO_TYPE套接字选项

返回套接字的类型,如SOCK_STREAM/SOCK_DGRAM/...

SO_USELOOPBACK套接字选项

本选项仅用于路由域(AF_ROUTE)的套接字.默认设置为打开,开启时,相应套接字将接收在其上发送的任何数据报的一个副本

IPv4套接字选项

IPv4处理,级别为IPPROTO_IP

IP_HDRINCL套接字选项

如是给一个原始IP套接字设置的,则必须为所有在该原始套接字上发送的数据报构造自己的IP首部
一般,在原始套接字上发送的数据报其IP首部是由内核构造的,有些应用需构造自己的IP首部

开启时,构造完整的IP首部.下列情况例外,
a. IP总是计算并存储IP首部校验和
b. 如将IP标识字段置为0,内核将设置该字段
c. 如源IP地址是INADDR_ANYIP将把它设置为外出接口的主IP地址
d. 如何设置IP选项取决于实现
有些实现取出预先使用IP_OPTIONS选项设置的任何IP选项,把其添加到我们构造的首部,其他实现要求,我们亲自在首部指定期望的IP选项.
e. IP首部中有些字段必须以主机字节序填写,有些字段必须以网络字节序添加

IP_OPTIONS套接字选项

允许在IP首部设置IP选项

IP_RECVDSTADDR套接字选项

导致所收到UDP数据报的目的IP地址由recvmsg函数作为辅助数据返回

IP_RECVIF套接字选项

导致所收到UDP数据报的接收接口索引由recvmsg函数作为辅助数据返回

IP_TOS套接字选项

允许我们为TCP/UDP/SCTP套接字设置IP首部中的服务类型字段
如给本选项调getsockopt,则用于放入外出IP数据报首部的DSCPECN字段中的TOS当前值将返回
应用进程可把DSCP设为用户和网络业务供应商预先协商号的某个值,以便接受预定的服务
IP_TOS设置成<netinet/ip.h>中定义的某个常值的应用应改为使用由用户指定的某个DSCP

IP_TTL套接字选项

可用本选项设置或获取系统用在从某给定套接字发送的单播分组上的默认TTL值,多播TTLIP_MULTICAST_TTL设置
调用getsockopt返回的是系统将用于外出数据报的字段的默认值

套接字选项

级别为IPPROTO_TCP

TCP_MAXSEG套接字选项

允许我们获取或设置TCP连接的最大分节大小(MSS),返回值是我们的TCP可发送给对端的最大数据量,通常是由对端使用SYN分节通告的MSS.除非TCP选择使用一个比对端通告的MSS小些的值,如该值在相应套接字的连接建立前取得,则返回值是未从对端收到MSS选项的情况下所用的默认值

如用上时间戳选项,则实际用于连接中最大分节大小可能小于本套接字选项的返回值,时间戳选项在每个分节要占用12字节的TCP选项容量,如TCP支持路径MTU发现功能,则它将发送的每个分节的最大数据量还可能在连接存活期内改变,如到对端的路径变动,值会调整,可由应用设置,一旦连接建立,本选项的值就是对端通告的MSS选项值,TCP不能发送超过该值的分节

TCP_NODELAY套接字选项

开启时,将禁止TCPNagle算法.默认下算法启动
算法:
如某个给定连接上有待确认数据,则原本应作为用户写操作之响应在该连接上立即发送相应小分组的行为就不会发生,直到数据被确认.小分组是小于MSS的任何分组,TCP总是尽可能发送最大大小分组,用于防止一个连接在任何时刻有多个小分组待确认

ACK延滞算法:
使得TCP在接收到数据后不立即发送ACK,而是等一小段时间,才发送ACKTCP期待在这一小段时间内自身有数据发送回对端,被延滞的ACK可由这些数据捎带,省掉一个TCP分节
在这里插入图片描述在这里插入图片描述

对于其服务器不再相反方向产生数据以便携带ACK的客户,ACK延滞算法存问题

fcntl函数

在这里插入图片描述
fcntl提供了与网络编程相关的如下特性
a. 非阻塞式I/O
通过F_SETFL设置O_NONBLOCK
b. 信号驱动式I/O
F_SETFL设置O_ASYNC文件状态标志
c. F_SETOWN
允许我们指定用于接收SIGIOSIGURG信号的套接字属主
d. F_GETOWN返回套接字当前属主

#include <fcntl.h>
int fcntl(int fd, int cmd, ...);

// 使用fcntl开启非阻塞式I/O
int flags;
if((flags = fcntl(fd, F_GETFL, 0)) < 0)
	err_sys("error");
// 设置代码
flags |= O_NONBLOCK;
// 取消代码
flags &= ~O_NONBLOCK;
if(fcntl(fd, F_SETFL, flags) < 0)
	err_sys("errot");

SIGIO/SIGURG仅在已用F_SETOWN给套接字设了属主(进程/进程组)才产生,F_GETOWN返回属主(进程/进程组).

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

raindayinrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值