9:选项

套接字选项

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.级别--SOL_SOCKET
选项名						说明								数据类型
SO_ERROR					获取待处理错误并清除				int
SO_KEEPALIVE				周期性测试连接是否存活				int[bool]
SO_RCVBUF					接收缓冲区大小					int
SO_SNDBUF					发送缓冲区大小					int
SO_RCVLOWAT					接收缓冲区低水位标记				int
SO_SNDLOWAT					发送缓冲区低水位标记				int
SO_RCVTIMEO					接收超时							timeval{
    
    }
SO_SNDTIMEO					发送超时							timeval{
    
    }
SO_REUSEADDR				允许重用本地地址					int[bool]
SO_REUSEPORT				允许重用本地端口					int[bool]
SO_TYPE						取得套接字类型					int
2.IPPROTO_IP
选项名						说明								数据类型
IP_TTL						存活时间							int
3.IPPROTO_IPV6
选项名						说明								数据类型
IPV6_DONTFRAG				丢弃大的分组而非将其分片			int[bool]
IPV6_PATHMTU				获取当前路径MTU					int
IPV6_USE_MIN_MTU			使用最小MTU						int[bool]
4.IPPROTO_TCP
选项名						说明								数据类型
TCP_MAXSEG					TCP最大分节大小					int
TCP_NODELAY					禁止Nagle算法					int[bool]

对个别选项的详细说明

通用类别

- SO_ERROR
套接字上产生某个错误时
1.若进程阻塞于含有此套接字的select上,立即返回.[读返回/写返回]
2.若进程用信号驱动I/O模型,给进程发SIGIO.
一般在此时是以SO_ERROR调getsockopt获得错误码的较好时机.
3.如阻塞于此套接字的read,read立即返回-1.errno被设为套接字错误码
4.如正对此套接字执行write,write立即返回-1.errno被设为套接字错误码.

- SO_KEEPALIVE
给一个套接字设置保持存活选项后,如2小时内在该套接字的任一方向上都没有数据交换,
TCP就自动给对端发一个保持存活探测分节.对端必须响应此分节.
1.对端以期望的ACK响应.
2.对端以RST响应.
该套接字的待处理错误被置为ECONNRESET.套接字本身关闭.
3.如无响应,且重传多次仍然无响应.
该套接字的待处理错误被置为ETIMEOUT.套接字本身关闭.
4.如套接字收到一个ICMP错误作为响应,则返回相应错误.
套接字本身被关闭.

一般由服务器使用.
用于针对已经崩溃或断网的客户端,释放本地与其通信的相关设施.
- SO_LINGER
指定close函数对面向连接的协议如何操作
struct linger
{
    
    
	int l_onoff;
	int l_linger;
};
对setsockopt的调用将根据其中两个结构成员的值形成下列3中情形之一:
1.如l_onoff为0.则关闭本选项.按默认设置处理close.
2.如l_onoff为非0且l_linger为0
则close某个连接时TCP将中止该连接[丢弃保留在套接字发送缓冲区的数据,发一个RST给对端.无正常的连接终止序列]
3.如l_onoff为非0且l_linger也为非0
则执行close,进程将休眠,直到以下任一条件被满足
a.该套接字的所有数据都已发送完且均被对方确认
b.延滞时间到.此时close返回值为EWOULDBLOCK.
对非阻塞套接字,上述说明无效.立即返回.
关于close/shutdown总结
1.shutdown+SHUT_RD
丢弃接收缓冲区现有内容,此后在套接字上不能再发出接收请求.
可以继续往套接字发送数据.
2.shutdown+SHUT_WR
套接字发送缓冲区中内容由内核后续发到对端,再发FIN.但shutdown后,不可再向其套接字写入待发送数据.
可以继续接收发给此套接字的数据.
3.close + l_onoff=0
此后无法通过此套接字执行数据发送和接收.
如close后底层对象引用计数变为0,释放底层对象.
且与其关联的发送缓冲区数据有内核后续发到对端,再发FIN.
与其关联的接收缓冲区数据立即丢弃.
4.close + l_onoff = 1, l_linger=0
此后无法通过此套接字执行数据发送和接收
如close后底层对象引用计数变为0,释放底层对象.
且与其关联的发送缓冲区,接收缓冲区数据均被丢弃.
主动发RST给对端.立即将此连接状态设为CLOSED
5.close + l_onoff = 1, l_linger != 0
此后无法通过此套接字执行数据发送和接收.
如close后底层对象引用计数变为0,释放底层对象.
且与其关联的发送缓冲区数据由内核后续发给对端,再发FIN
与其关联的接收缓冲区数据被丢弃.
如在变为CLOSED状态前,指定的时间到,close返回EWOULDBLOCK.
- SO_RCVBUF和SO_SNDBUF
每个套接字都有一个发送缓冲区和一个接收缓冲区
对TCP,套接字接收缓冲区中可用空间大小限定了TCP通告对端的窗口大小.
不允许对端发超过本端所通告窗口大小的数据,可保证接收缓冲区不会溢出.[流量控制]
对UDP,当接收到的数据报装不进套接字接收缓冲区时,直接丢弃.
这两个套接字选项允许改变两个缓冲区的默认大小.
TCP的窗口规模选项是在建立连接时用SYN分节与对端互换得到的.
对客户,
SO_RCVBUF选项需在调connect之前设置
对服务器,
该选项需在调listen前给监听套接字设置

TCP套接字缓冲区的大小至少应该是相应连接的MSS值的4倍
对全双工管道,
管道的容量称为带宽-延迟积,通常将带宽[bit/s]和RTT[秒]相乘,
再将结果由位转换为字节.
- SO_RCVLOWAT和SO_SNDLOWAT
每个套接字还有一个接收低水位标记[默认1]和一个发送低水位标记[默认2048]
接收低水位标记定义让select返回'可读'时,套接字接收缓冲区所需的最小数据量.
发送低水位标记是定义让select返回'可写'时,套接字发送缓冲区可用空间最小大小.

UDP也使用发送低水位标记,
由于UDP套接字的发送缓冲区中可用空间的字节数从不改变[UDP不为应用传来的数据报保留副本],只要一个UDP套接字的发送缓冲区大小大于该套接字的低水位标记,该UDP套接字就总是可写.
- SO_RCVTIMEO和SO_SNDTIMEO
允许给套接字的接收和发送设置一个超时值
关联的参数是struct timeval
通过设置其值为0来禁止超时.[默认情形]
- SO_REUSEADDR和SO_REUSEPORT
对SO_REUSEADDR
1.允许一个监听套接字绑定众所周知端口A,即使有一个已经连接套接字本地端端口地址为A.
所有TCP服务器均应指定此选项.
若为指定,对监听套接字执行bind到A会失败
2.存在多个IP地址作为本机地址的主机上
我们可以分别以每个本地IP+已经端口A,通配IP+已知端口A
针对本机某个TCP服务提供多个监听套接字用于提供连接服务.
若未设置SO_REUSEADDR选项,
对非首个绑定在端口A的监听套接字执行bind时,将出错.
3.允许单个进行针对一个端口A,分别以本机不同IP产生监听套接字.
UDP服务器可用此方法确定接收到数据报的具体目的IP地址.
4.一般对于UDP
其余SO_REUSEADDR下,即使建立多个绑定套同一本机IP+已知端口A的套接字也是允许的.

对SO_REUSEPORT
1.允许在本机,以同一本机IP+已知端口A创建多个套接字
需要每个套接字均指定此选项

总结:
在所有TCP服务器程序中,调bind前设置SO_REUSEADDR套接字选项
一个可能隐患是,对绑定了通用本机地址的服务套接字1,
若后续有一绑定本机具体IP+同一端口A的套接字2创建,
后续本机收到的数据报,可与1,2都匹配.将发给匹配度更高的套接字.
可能被利用.

IPV4类别

IPPROTO_IP
- IP_RECVDSTADDR
导致所收到UDP数据报的目的IP地址由recvmsg函数作为辅助数据返回
- IP_RECVIF
导致所收到UDP数据报的接收接口索引由recvmsg作为辅助数据返回

IPV6类别

IPPROTO_IPV6
-	IPV6_DONTFRAG
开启本选项将禁止为UDP套接字或原始套接字自动插入分片首部,
外出分组中大小超过发送接口MTU的那些分组将被丢弃.
- IPV6_PATHMTU
用于获取路径MTU发现功能确定的当前MTU
- IPV6_USE_MIN_MTU
若本选项设为1,表示路径MTU发现不必执行.因为分组将以IPV6最小MTU发送.
若本选项设为0,路径MTU发现需执行.
若本选项设为-1,路径MTU发现对单播目的地执行.对多播目的地将以IPV6最小MTU发送.

TCP

IPPROTO_TCP

猜你喜欢

转载自blog.csdn.net/x13262608581/article/details/111226819
9