socket选项梳理

概述

socket套接字可以通过以下API进行选项的设置和获取:

  • getsockoptsetsockopt
  • fcntl函数
  • ioctl函数

getsockopt和setsockopt

这两个函数仅用于操作socket描述符,getsockopt用于获取指定socket的选项,setsockopt用于给指定socket设置选项。socket支持多种选项,选项按照leveloptname的层次进行分类。它们的函数原型如下:

#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);
- sockfd : 已经打开的socket描述符
- level : 选项的等级
- optname : 选项的名称
- optval : 针对getsockopt,optval用于存放获取到的选项结果;针对setsockopt,optval用于指定要设置的选项值
- optlen : 选项值对应的长度

leve和optname说明

leve包括:

  • SOL_SOCKET : 通用级别的选项
  • IPPROTO_IP : IP特有的选项
  • IPPROTO_ICMPV6 : ICMPv6特有的选项
  • IPPROTO_IPV6 : IPv6特有的选项
  • IPPROTO_IP/IPPROTO_IPV6 : IPv4和IPv6通用的选项
  • IPPROTO_TCP : TCP特有的选项

通用套接字选项

通用套接字选项,是一些协议无关的选项。下面列举并说明一些常用的该级别的optname:

SO_BROADCAST

本选项是一个标志,作用是开启或禁止套接字广播的能力,仅针对UDP有效,应该在发送广播报文之前设置该选项,如果该选项没有设置,应用程序向广播地址发送报文,内核会进行错误校验,并返回EACCES错误码给应用程序。

SO_DEBUG

本选项是一个标志,仅针对TCP有效。当开启本选项时,内核为发送的每一个TCP分段,记录详细信息,并保存在内核的环形缓冲区内,可以通过trpt命令获取这些信息。

SO_DONTROUTE

本选项是一个标志,置上该选项的socket,在发送报的时候,不会去查路由表的默认网关,只有目的地址和本机在一个直连网段,报文才能发送成功,否则哪怕目的地址三层可达,也会返回ENETUNREACH

SO_ERROR

本选项是一个数值,当socket发生错误时,该选项内容就会被设为相应的错误,且只能被获取不能被修改。应用程序获取这个错误信息方式为:

  • 如果调用select,那么将直接返回可读或可写
  • 如果应用程序使用信号驱动的IO模型,那么会给进程或进程组发送一个SIGIO信号

此时调用getsockopt可以获取到so_error的值,随后so_error会被设为0。

SO_KEEPALIVE

本选项是一个标志位,置上之后,如果一个TCP连接2个小时都没有交换报文,那么本机会向对端发送keepalive报文,如果对端正常响应,那么连接继续保持,不返回任何信息给应用程序;如果对端响应RST包,则将so_error设为ECONNRESET并关闭socket;如果对方没有响应,则将so_error设为ETIMEOUT,并且关闭socket;如果返回了ICMP错误,那么将这个错误返回给应用程序,并且关闭socket。

SO_LINGER

本选项是个数值,数值的数据类型为struct linger,作用是延迟关闭socket:

struct linger {
	int l_onoff;//开关
	int l_linger;//延迟时间,单位是秒
}
  • 如果l_onoff为0,那么关闭延迟发送功能,进程在调用close之后立即返回,内核会将socket发送缓冲队列中的剩余数据发往对端,最后再发送FIN包进行四次挥手
  • 如果l_onoff非0,l_linger为0,意味着开启延迟功能,但是延迟时间为0,此时内核会丢弃发送缓冲区中的任何数据,并发送RST包给对端,不经过四次挥手过程,TCP连接直接进入CLOSE状态
  • 如果l_onoff非0,l_linger非0,那么TCP经过l_linger延迟之后关闭,socket如果是阻塞的,close不会立即返回,内核会将发送缓冲区中的数据继续发给对端。如果数据在延迟时间之内全部发给对端,在收到对端的FIN包的确认包之后,close返回0;如果延迟时间内数据发不完,那么时间一到,就返回EWOULDBLOCK。因此进程有必要对close的返回值做检查,以判断数据是否成功发给对端。

虽然在做了延迟关闭之后,可以通过close的返回值判断数据是否全部发给对端,如果想要数据完全被对端接收之后,再关闭socket,那么可以先shoudown掉socket,然后调用read,如果read返回0,那么一定收到对端的FIN包。

但是还有个问题,收到对端的FIN包仅说明数据包已经到了对端的接收缓冲区,并不能证明对端应用程序已经收到。解决方案是使用应用级ACK,也即双方约定一个结束符,双方收到以结束符为内容的报文后,再关闭socket,保证所有数据双方均已完全收到。

SO_OOBINLINE

本选项为标志位,TCP的带外数据默认情况下是保存在带外缓冲区内,SO_OOBINLINE非0时,带外数据和正常数据一样,放在普通数据的接收缓冲区内。

SO_RECVBUF和SO_SNDBUF

本选项为int类型数值选项,SO_RECVBUF用于设置socket接收缓冲区大小,SO_SNDBUF用于设置发送缓冲区大小。TCP通过滑动窗口实现流量控制,缓冲区的可用空间限制了滑动窗口的大小。由于socket的窗口规模在发送SYN包的时候交换,因此客户端要在调用connect函数之前设置缓冲区大小,服务端要在调用bind之前设置缓冲区大小,服务端accept返回的socketfd将继承bind socketfd的缓冲区大小。

SO_RCVLOWAT和SO_SNDLOWAT

本选项为int类型的数值选项,SO_RCVLOWATSO_SNDLOWAT分别用于设置接收缓冲区和发送缓冲区的低水位值。

  • SO_RCVLOWAT:接收缓冲区中的数据大于该值时,select函数才返回可读,默认大小1字节
  • SO_SNDLOWAT:发送缓冲区中的数据大于该值时,select函数才返回可写,默认大小2048字节

SO_RCVTIMEO和SO_SNDTIMEO

本选项为struct timeval类型的数值选项,分别用于设置接收和发送的函数的超时时间。

  • 影响的接收函数:write, writev, send, sendto, sendmsg
  • 影响的发送函数:read, readv, recv, recvfrom, recvmsg

超时时,errno被设置为EAGAIN或EWOULDBLOCK。仅对阻塞模式的socket有效,非阻塞模式的socket调用上面的函数还是立即返回。

SO_REUSEADDR

本选项为标志位,SO_REUSEADDR的作用为:

  1. 允许服务端应用程序绑定的端口上面已经有连接,因为可能是服务端主进程挂了,子进程还在这个端口上跑,主进程如果想成功重新启动,必须设置上这个标志。
  2. 允许同一个端口上起多个服务进程,这些socket绑定不同的IP地址,内核根据IP地址的不同,将数据发送给对应的socket
  3. 允许同一个进程上面起多个socket,绑定相同端口不同IP,这样UDP就能够获取到客户端访问的目的IP是多少。
  4. 允许完全重复捆绑

SO_TYPE

本选项是一个int类型的数值选项,用于获取socket的类型,如SOCK_DGRAMSOCK_STREAM

IPv4套接字选项

IP_OPTIONS

本选项是int型的数值选项,允许应用程序给IP头设置选项,或获取头部选项。

IP_RECVSDTADDR

本选项是标志位,置上之后,允许对UDP socket调用recvfrom的时候,能够以辅助数据的形式获取到客户端报文的目的地址。

IP_RECVIF

本选项是标志位,置上之后,允许对UDP socket调用recvfrom的时候,能够以辅助数据的形式获取到客户端报文的目的接口。

IP_TOS

本选项是int型的数值选项,允许对TCP、UDP的IP头中的tos字段进行设置

IP_TTL

本选项是int型的数值选项,允许对单播报文的TTL默认值进行设置,或者获取。

TCP套接字选项

TCP_MAXSEG

本选项是int类型的数值选项,允许为TCP设置MSS值,返回值是本端TCP能发送给对端的最大数据报文。这个值通过SYN包来宣告,连接一旦建立,只能缩小不能增大。

TCP_NODELAY

本选项是标志位,开启后将禁止TCP使用Nagle算法,这个算法默认是开启的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值