文章目录
  1. socket选项简介
  2. SO_REUSEADDR选项
  3. SO_RCVBUF与SO_SNDBUF
  4. SO_RCVLOWAT与SO_SNDLOWAT
  5. SO_LINGER选项

socket选项简介

下面两个函数专门用来读取与设置socket文件描述符属性。

1
2
3
4
5
6
7
8
9
10
11
/*
引用方式: #include <sys/socket.h>
level: 指定协议类型
opt_name: 指定选项
opt_val: 存放选项的值的地址
len: 存放选项的值的地址的长度
返回0: 成功 || 返回-1并设置errno: 失败
*/
int getsockopt(int sockfd, int level, int opt_name, void * opt_val, socklen_t * len);

int setsockopt(int sockfd, int level, int opt_name, const void * opt_val, socklen_t len);

如下表是一些常用的socket选项。

 

对服务器来说,有些socket选项只能在调用listen函数前针对监听socket设置才有效。对于这些监听socket,只能由accept函数返回。而此时接受的连接至少已经完成TCP三次握手的前两次步骤,但有些选项需要在TCP同步报文段中设置,因此这些选项必须在调用listen函数前针对监听socket设置,然后连接的socket将其继承,这些选项包括SO_DEBUG | SO_DONTROUTE | SO_KEEPALIVE | SO_LINGER | SO_OOBINLINE | SO_RCVBUF | SO_RCVLOWAT | SO_SNDBUF | SO_SNDLOWAT |TCP_MAXSEG | TCP_NODELAY。

而对于客户端来说,这些socket选项应该在调用connect函数之前设置。

下面讨论几个重要的socket选项。

SO_REUSEADDR选项

服务器设置socket的SO_REUSEADDR选项来强制使用被处于TIME_WAIT状态的连接占用的socket地址。此外,设置内核参数/proc/sys/net/ipv4/tcp_tw_reuse来快速回收被关闭的socket地址

SO_RCVBUF与SO_SNDBUF

SO_RCVBUF与SO_SNDBUF选项分别表示TCP接收缓冲区与发送缓冲区的大小。而事实上,操作系统会将设置的缓冲区大小加倍再作为缓冲区大小,而且不得小于某个最小值(TCP接收缓冲区最小值为256字节,发送缓冲区最小值为2048字节)。此外,可以设置/proc/sys/net/ipv4/tcp_rmem与/proc/sys/net/ipv4/tcp_wmem来使TCP接收/发送缓冲区没有大小限制。

SO_RCVLOWAT与SO_SNDLOWAT

当TCP接收缓冲区中可读数据的总数大于其低水位标记SO_RCVLOWAT时,I/O复用系统调用将通知应用程序可从对应的socket上读取数据。

当TCP发送缓冲区中空闲空间的大小大于其低水位标记SO_SNDLOWAT时,I/O复用系统调用将通知应用程序可向对应的socket上写入数据。

SO_RCVLOWAT与SO_SNDLOWAT均默认为1字节。

SO_LINGER选项

SO_LINGER选项控制close函数在关闭TCP连接时的行为。默认情况下,close函数关闭socket后,close立即返回,TCP模块负责将socket对应的TCP发送缓冲区中残留的数据发送给对方。

设置SO_LINGER选项时,需要在setsockopt函数中传递一个linger结构体。定义如下。

1
2
3
4
5
6
7
8
9
/*
引用方式: #include <sys/socket.h>
l_onoff: 开启(非0)还是关闭(0)该选项
l_linger: 滞留时间
*/
struct linger{
int l_onoff;
int l_linger;
};

根据l_onoff与l_linger的值,close函数有3种处理方式。

  • l_onoff为0。close采用默认处理方式;
  • l_onoff为1,l_linger为0。close函数立即返回,TCP模块丢弃被关闭的socket对应的TCP发送缓冲区中残留的数据,同时给对方发送一个复位报文;可见这给服务器提供了异常终止连接的方法;
  • l_onoff为1,l_linger大于0。若socket是非阻塞的,close将立即返回;若socket是阻塞的,则close将等待l_linger时间,若在这期间TCP模块发送完发送缓冲区残留的数据并收到对方的确认,close返回0,否则返回-1并设置errno为EWOULDBLOCK。