套接字选项

有几个函数可以设置影响套接字的选项

  • getsockopt 和 setsockopt函数
  • fcntl 函数
    • 把套接字设为非阻塞
    • 信号驱动式I/O中设置套接字属主(进程)
  • ioctl函数
getsockopt函数 和 setsockopt函数
#include 

int setsockopt(int sockfd, int leval, int opename, const void* optval, socklen_t optlen);
    函数返回值:若成功则为0,若出错则为-1。

int getsockopt(int sockfd, int level, int optname, void* optval, socklen_t *opelen);
    函数返回值:若成功则为0,若出错则为-1。
  • 参数sockfd
    指向一个打开的套接字描述符。

  • 参数level
    表示级别,解释选项的代码作用于通用套接字,或为作用域某个特定的协议套接字。

  • 参数*optval
    optval 是一个指向某个变量的指针,stesockopt从*optval中取得选项待设置的新值,getsockopt则把获取的值保存在这个变量中。

  • 参数*opelen 或 optlen
    optlen指定选项*optval的大小。

    eg:  setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));  // 开启经受时延算法
    

    *opelen是一个指向某个地址的指针,其所指

套接字选项
  • level
    #include 
    
    #include 
    
  • optname
    #include 
    
    #include 
    
  • 标志
    套接字选项可以粗分为2类:
    • 启用或禁止某个特性的二元选项,称为标志选项。
    • 取得并返回我们可以设置或检查的特定值的选项,称为值选项。
level optname get set 说明 标志 数据类型
SOL_SOCKET SO_KEEPALIVE 周期性的检测连接是否存活 int
SOL_SOCKET SO_RCVBUF 接收缓冲区的大小 int
SO_SNDBUF 发送缓冲区的大小 int
SO_RCVTIMEO 接收超时 timeval{}
SO_SNDTIMEO 发送超时 timeval{}
SO_REUSEADDR 允许重用本地地址 int
SO_REUSEPORT 允许重用本地端口 int
IPPROTO_IP
IPPROTO_TCP TCP_NODELAY 禁止Nagle算法 int
SO_KEEPALIVE 套接字选项

给一个套接字设置保持存活(keep-alive)选项后,如果在2小时内在该套接字的任一方向上都没有数据交换,TCP就自动给对端发送一个保持存活探测分节, 这是一个对端必须响应的分节,会导致下列3种情况:

  • 对端以期望的ACK回应,应用进程得不到通知。在又经过2小时后,TCP将发出新的探测分节。
  • 对端以RST响应,它告知本端TCP:对端已崩溃已重新启动。
  • 对端对保持存活探测分节没有任何响应。TCP将发送另外8个分节,两两像个75秒,试图得到一个响应。
SO_RCVBUF 和 SO_SNDBUF 套接字选项

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

对于UDP来说,当接受到的数据报装不进套接字缓冲区时,该数据报就被丢弃。

对TCP设置套接字接收缓冲区时函数调用顺序很重要。这是因为TCP的窗口规模选项是在建立连接时用SYN分节与对端互换得到的。
所以对于客户端而言,必须在调用connect之前设置。
对于服务器而言,必须在调用listen之前设置。

SO_RCVTIMEO 和 SO_SNDTIMEO 套接字选项

这2个选项允许我们给套接字的接收和发送设置一个超时值。默认情况下,超时都是禁止的。

struct timeval {
    time_t tv_sec;         // 秒
    suseconds_t tv_usec    // 微妙
}

接收超时影响的5个函数:read,readv,recv,recvfrom和recvmsg。
发送超时影响的5个函数:write,writev,send,sendto 和 sendmsg。

SO_REUSEADDR 和 SO_REUSEPORT 套接字选项

SO_REUSEADDR 和 SO_REUSEPORT 允许启动一个监听服务器绑定一个端口,即使以前建立该端口的连接仍然存在。这个情况通常是:
【1】启动一个监听服务
【2】连接请求到达,派生1个子进程处理
【3】监听服务器终止,但子进程继续外现有连接是上的客户提供服务
【4】重启监听服务器

默认情况下,服务器在4步骤时调用bind时,由于它试图捆绑一个现有连连接(子进程)上的端口,bind调用会失败。但是如果设置了SO_REUSEADDR和SO_REUSEPORT,那么bind将会成功。所有的TCP服务器都应该指定本套接字选项。

  • TIME_WAIT状态有两个存在的理由:
    1. 可靠地实现TCP全双工连接的终止
      如果服务器最后发送的ACK因为某种原因丢失了,那么客户一定会重新发送FIN,这样因为有TIME_WAIT的存在,服务器会重新发送ACK给客户,如果没有TIME_WAIT,那么无论客户有没有收到ACK,服务器都已经关掉连接了,此时客户重新发送FIN,服务器将不会发送ACK,而是RST,从而使客户端报错。也就是说,TIME_WAIT有助于可靠地实现TCP全双工连接的终止。
    2. 允许老的重复分节在网络中消逝
      如果没有TIME_WAIT,我们可以在最后一个ACK还未到达客户的时候,就建立一个新的连接。那么此时,如果客户收到了这个ACK的话,就乱套了,必须保证这个ACK完全死掉之后,才能建立新的连接。也就是说,TIME_WAIT允许老的重复分节在网络中消逝。
SO_RCVLOWAT 和 SO_SNDLOWAT 套接字选项

每个套接字还有一个接收低水位标记和一个发送低水位标记,他们由select函数使用。

接收低水位标记是让select返回"可读"时套接字接收缓冲区中最小的数据量,对于TCP,UDP和SCTP套接字,其默认值为1。

发送低水位标记是让select返回"可写"时套接字发送缓冲区所需要的最小可用空间。对于TCP套接字,默认值通常为2048。

你可能感兴趣的:(套接字选项)