欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

UNP卷一chapter7 套接字option

程序员文章站 2022-07-14 22:05:41
...

以下知识点来均来自steven先生所著UNP卷一(version3),刚开始学习网络编程,如有不正确之处请大家多多指正。

本章节读下来,了解套接字的option有哪些,分别对应的level,当然对于通用套接字、IPv4、IPv6、tcp等option还好理解,但针对sctp的option实在没耐心看下去(暂且跳过,后面有用到时再返回来看看)。

1、getsockopt函数(获取套接字option)和setsockopt函数(设置套接字option)

#include<sys/socket.h>
int getsockopt(int sockfd, int level, int optname, void* optval, socklen_t* oplen);//此处optval为值-结果参数,值为0表示禁止,不为0表示启用
int setsockopt(int sockfd, int level, int optname, const void* optval, socklen_t optlen);
//均返回:若成功则为0,若出错则为-1

2、通用套接字option(介绍几个主要的)

a、SO_KEEPALIVE套接字选项(其目的在于关闭无效的套接字连接):开启后,如果2小时内在该套接字的任一方向上都没有数据交换,tcp就自动给对端发一个保持存活探测分节,对端必须响应tcp分节。由于对端响应tcp分节又存在三种特殊情况:

(1)对端以期望的ACK分节响应。应用进程得不到通知。再又经过仍无动静的2小时后,tcp将发出另一个探测分节。

(2)对端以RST响应,它告知本端tcp:对端已崩溃且已重新启动。该套接字的待处理错误被置为ECONNRESET,套接字本身则被关闭。

(3)对端对保持存活探测分节没有任何响应。

b、SO_LINGER套接字选项

struct linger {
	int l_onoff;//0=off,非0=on
	int l_linger;//linger time
};

setsockopt将根据其中两个结构成员的值形成下列3种情况:

(1)若l_onoff为0,则关闭本选项。tcp默认设置生效,即close立即返回;

(2)若l_onoff为非0值且l_linger为0,那么当close某个连接时tcp将中止该连接。即tcp将丢弃保留在套接字发送缓冲区中的任何数据,并发送一个RST给对端,而没有通常的四分组连接终止序列。(即没有了time_wait,相当不好)

(3)若若l_onoff为非0值且l_linger为非0,那么当套接字关闭时内核将拖延一段时间(即延滞时间哈)。若套接字发送缓冲区中仍残留有数据,那么进程将被投入睡眠,直到所有数据都已发送完且均被对方确认或延滞时间到。

介绍一下应用级确认(获知对端应用进程已读取我们的数据的一种方法):也就是说,当读到一个字节数据时,服务器已获取全部数据,于是进行四次挥手,过程见下图;

UNP卷一chapter7 套接字option

c、SO_RCVBUF和SO_SNDBUF套接字option

tcp:套接字接收缓冲区中呵用空间的大小限定了tcp通告对端的窗口大小。tcp套接字接收缓冲区不可能溢出,因为不允许对端发出超过本端所通告窗口大小的数据——tcp的流量控制。

当设置tcp套接字接收缓冲区的在砂眼时,函数调用的顺序很重要。对于客户,SO_RCVBUF选项必须在调用connect之前设置;对于服务器,该选项必须在调用listen之前给监听套接字设置。已连接套接字的缓冲区大小从监听套接字继承而来。

tcp需要为每个分节保留副本,以供确认之用。

udp:当接收到的数据报装不进套接字接收缓冲区时,该数据报就被丢弃。

d、SO_REUSEADDR和SO_REUSEPORT套接字选项

SO_REUSEADDR套接字起到以下4个不同的功用:

(1)允许启动一个监听服务器并捆绑其众所周知端口,即使以前建立的将该端口用作它们的本地端口连接仍然存在。(此情况所遇见的场景见书上分析P167)

(2)允许在同一端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的本地IP地址即可。

(3)允许单个进程捆绑同一端口到多个套接字上,只要每次捆绑指定不同的本地IP地址即可。

(4)允许完全重复的捆绑:当一个IP地址和端口已绑定到某个套接字上时,如果传输协议支持,同样的IP地址和端口还可以捆绑到另一个套接字上。(本特性仅支持UDP套接字)

对SO_REUSEADDR选项的总结:

(1)在所有tcp服务器程序中,在调用bind之前设置SO_REUSEADDR套接字选项;

(2)当编写一个可在同一时刻在同一主机上运行多次的多播应用程序时,设置SO_REUSEADDR套接字选项,并将所参加多播组的地址作为本地IP地址捆绑。(第2点其实不太了解)

3、tcp套接字选项(开启本选项将禁止tcp的Nagle算法,默认情况下Nagle算法是启动)

Nagle算法常与另一个ack延滞处落去联合使用:算法使得tcp在接收到数据后不立即发送ack,而是等待一小段时间,然后才发送ack。若tcp期待在这一小段时间内自身有数据发送回对端,被延滞的ack就可以由这些数据捎带,从而省掉一个tcp分节。(此特点的运用见书上习题7_8、7_9)。书上P173列举了一个开启Nagle算法时由服务器回显的六个字符。

4、sctp套接字选项(此小节先行跳过,等需要时再回来看看)

5、fcntl函数(file control,文件控制,该函数可执行各种描述符控制操作)

#include<fcntl.h>
int fcntl(int fd, int cmd, ... /*int arg*/);//返回:若成功则取决于cmd,若出错则为-1

fcntl函数相应的命令及文件状态标志,如下列举:

F_SETFL,O_NONBLOCK  设置套接字为非阻塞式I/O型 

F_SETFL,O_ASYNC  设置套接字为信号驱动式I/O型

F_SETOWN  设置套接字属主

F_GETOWN  获取套接字属主

开启非阻塞式I/O代码

int flags;

if ((flags = fcntl(fd, F_GETFL, 0)) < 0)//获取描述符fd的文件标志,并将返回值赋给flags
	err_sys("F_GETFL error");
flags |= O_NONBLOCK;//将flags的对应位置与O_NONBLOCK相或,即将对应位置置位,其它位置保持不变
if (fcntl(fd, F_SETFL, flags) < 0)//设置好非阻塞描述符
	err_sys("F_SETFL error");

关闭非阻塞式I/O代码

flags &= ~O_NONBLOCK;
if (fcntl(fd, F_SETFL, flags) < 0)
	err_sys("F_SETFL error");