套接口选项

设置和影响套接口选项的方法有

1.getsockopt和setsockopt

2.fcntl

3.ioctl

getsockopt和setsockopt

这两个方法仅适用于套接字

有两种基本类型的套接口选项:打开或关闭某个特性的二进制标志,取得并返回我们可以设置或检验的特定值的选项,标有标志的列指明是否为标志选项,对于这些项,0表示关闭标志,非0表示打开标志。

并不是所有的系统的套接字都支持所有的选项,必要时候自行验证一番。

套接字的不支持分为两种

1.未实现相关的定义,比如SO_REUSEPORT宏未定义

2.定义了名字,但并不支持,比如SO_REUSEPORT虽然定义,调用getsockopt却会报错。

针对这两种不支持的测试

1.#ifdef   #else   #endif

2.getsockopt返回失败或者取回的值为空。

套接口选项应该什么时候设置

抽取redis的一段代码来示例

//监听套接字接收accept事件的处理器

acceptTcpHandler

{

//accept的包裹函数

anetTcpAccept

//设置socket的选项:设置非阻塞;禁用Nagle算法;设置keepalive

acceptCommonHandler

}

某些设置要更早一些,比如SO_RCVBUF和SO_SNDBUF,需要在服务器的监听套接口上设置,或者在未connect的客户端套接口上设置。

套接口基本选项

基本选项是协议无关的,但有些选项只能应用于特定类型的套接口中

SO_BROADCAST

此选项禁止或使能进程发送套接口广播的能力。只有数据报套接口支持广播,还必须是支持广播的网络。你不可能在一个点对点网络上发起广播。

SO_DEBUG

仅有TCP支持,当打开时,内核对TCP在此套接口上的发送和接收消息都做详细跟踪,这些信息保存在内核缓冲区,由程序trpt进行检查。

SO_ERROR

当套接口发生错误时,套接口名为so_error的变量被设置为标准的UNIX Exxx值的一个,它称为套接字的待处理错误。

内核可以通过select等多路复用I/O立即通知调用进程,进程可以通过SO_ERROR选项获取so_error的值,so_error随后由内核恢复为0.

当进程调用read且没有数据返回时,如果so_error为非0值,则read返回-1且errno设置为so_error的值,so_error随后复位为0.如果此套接口上有数据排队,则read返回那些数据,而不是返回错误条件。

如果在进程调用write时,so_error为非0值,则write返回-1值,并且errno设置为so_error的值,so_error也被复位为0.

SO_KEEPALIVE

给TCP一个保存存活选项以后,如果2个小时内此套接口的任何一方都没有数据交换。TCP就自动给对方发送一个保持存活探测分节,这是一个必须回复的TCP分节,它会导致以下三种情况:

1.对方回复一个正常的ACK,应用进程得不到任何通知(因为一切正常)。

2.对方以RST响应,它告诉本地TCP,对方已崩溃并且重新启动,套接口的待处理错误被设置成ECONNRESET,套接口本身被关闭。

3.对方对保持存活分节无任何响应,源自berkeley的TCP将发送另外8个分节,每隔75s一个,试图得到响应,如果对TCP的探测存活分节没有响应,套接口的错误被设置成ETIMEOUT,套接字本身被关闭。但如果收到某个ICMP的错误,则返回相应的错误。

主要是检测对方主机是否崩溃,如果对方进程崩溃,它的TCP将跨连接发送一个FIN,这可以通过多路复用检测到。

所有的TCP探测分节均无响应,也不意味这连接已中断,也有可能是某个中间路由器暂时性的有问题,也就有可能关闭一个有效连接。

这个选项一般由服务器使用,因为如果客户主机崩溃,服务器将永远不知道,并继续等待不会到来的输入,这称为半打开连接,保持存活消息将检测这些连接并终止它们。

当TCP对端发生某些事件必须检测时的一些手段

SO_LINGER选项

只是函数close对面向连接的套接字如何操作,缺省设置是立即返回,如果有数据残留在套接口发送缓冲区,系统试着将这些数据发送给对端。

SO_LINGER可以使我们改变这些缺省操作。SO_LINGER的主要作用是去掉TIME_WAIT状态,使重启服务器进程是够重新绑定端口。作为替代,我们可以在bind的时候使用SO_REUSERADDR选项。

SO_LINGER的另一个作用是,告诉我们发送的数据和FIN已由对方TCP确认,它并不能告诉我们对方应用进程是否读取了数据,如果不设置该选项,我们连对方是否接收了数据都不知道。

close的缺省操作,立即返回

设置了SO_LINGER,并且l_linger为正值时的close

让客户知道服务器已读其数据的一个方法是:调用SHUT_WR的shutdown,并等待对方close连接的本地端。

使客户端知道服务器已读其数据的另一个方式是:使用应用级的ACK。

SO_RCVBUF和SO_SNDBUF

每一个套接口都有一个接收缓冲区和一个发送缓冲区

接收缓冲区被TCP和UDP用来保存收到的数据,一直保存到应用程序来读。对于TCP来说,接收缓冲区的大小就是告知对方的窗口大小。TCP套接口接收缓冲区不可能溢出,因为对方不可能发出超出所通告窗口大小的数据,这就是TCP的流量控制。如果对方无视窗口大小而发出了超出窗口大小的数据,则接收方TCP将丢弃它。对于UDP来说,如果接收到的数据装不进套接口缓冲区时,将会丢弃它。UDP是没有流量控制的,快的发送方可以轻易的淹没慢的接受者。这导致接收方的UDP丢弃数据报。

当设置TCP套接字缓冲区大小时,函数调用顺序非常重要。TCP的窗口规模是在建立连接时用SYN交换来的,对于客户来说,必须在connect之前设置,对于服务器来说,意味着调用listen之前必须给监听套接字设置缓存区大小。给已连接的套接字设置该选项可能没有任何影响。

TCP套接字缓冲区的大小至少是MSS的三倍,并且必须是MSS的偶数倍,因为客户TCP必须为客户数据保存一份拷贝,直至接收到对端的确认。

fpathconf获取套接字缓冲区的上限。

SO_RCV_LOWAT和SO_SNDLOWAT

每个套接口也都有一个发送低潮限度和一个接收低潮限度。

接收低潮限度是在多路复用API返回可读时,套接口接收缓冲区至少有的数据量。对于TCP和UDP,缺省值为1.

发送低潮限度是在多路复用API返回可写时,套接口发送缓冲区至少有的可用空间。对于TCP套接字,其值常缺省为2048.UDP没有发送缓冲区,只有发送缓冲区大小,对于UDP来说,只要发送缓冲区大小大于套接口的低潮限度,UDP套接口就总是可写的。

SO_RCVTIMEO和SO_SNDTIMEO

给套接字设置一个接收和发送超时,缺省超时是禁止的。

接收超时影响:read、readv、recvfrom、recv和recvmsg

发送超时影响:write、writev、send、sendto和sendmsg。

SO_REUSEADDR和SO_REUSEPORT

SO_REUSEADDR通常为以下4个目的服务

1.SO_REUSEADDR允许启动一个监听服务器并绑定其众所周知端口,哪怕以前建立的将此端口用作本地端口的连接仍然存在。

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

3.SO_REUSEADDR允许单个进程捆绑同一端口到多个套接字,只要每个套接字捆绑不同的本地IP端口。

4.SO_REUSEADDR还允许完全重复的绑定,当一个IP和端口捆绑到一个套接字时,允许把同一个IP和端口捆绑到另一个套接字。一般来说,这个特性仅在支持多播的系统上才有,而且仅对UDP套接字(TCP不支持多播)。这个作用并不是每个系统都支持。

TCP套接口选项

TCP_KEEPALIVE

由于SO_KEEPALIVE的超时时间是2小时,并且难以修改,在linux上通常还会设置TCP_KEEPALIVE,设置TCP_KEEPALIVE仅在SO_KEEPALIVE套接口选项打开时才有效。

TCP_NODELAY

禁止TCP的nagle算法,缺省时,该功能是打开的。

Nagle算法:如果给定TCP连接上有待确认的分组,则直到现有数据被确认前,不往TCP上发送任何小分组。小分组即小于MSS的分组。如果可能,TCP总是发送最大大小的分组;Nagle算法的目的是防止TCP连接上有待确认的小分组存在。

Nagle算法常与另一个TCP算法一起使用,延滞ACK算法,此算法导致在接收到数据时不立即发送ACK。而是由TCP等待一小段时间(50-200ms)才发出ACK,所希望的是这段时间TCP有数据回复给对端,这样ACK可以捎带在这些数据上。又是就节省了一个TCP分节。

不适合Nagle和延滞ACK的客户端:以若干小数据分片发送单个逻辑请求给服务器的客户。对这类客户的修复办法是

1.使用writev合并小数据分片为完整的逻辑请求,然后发送

2.拷贝属于单个逻辑的多个小数据分片到一个缓冲区,然后完整发送

3.设置TCP_NODELAY并继续调用write两次。


 fcntl函数

fcntl、ioctl和路由套接口操作小结

从表中来看,posix推荐使用fcntl

时间: 2024-10-12 04:47:23

套接口选项的相关文章

fuser:用文件或者套接口表示进程

fuser:用文件或者套接口表示进程 作用:fuser命令用文件或者套接口表示进程. 用法:fuser [-a | -s | -c] [-4 | -6] [-n space] [-k [-i] [-signal]] [-muvf] name … 或 fuser -l 或 fuser -V 主要选项如下. — -a:显示在命令行指定的所有文件,默认情况下,至少被一个进程访问的文件才能显示出来. — -c:同选项-m,用于同Posix进行兼容. — -f:忽略,用于同Posix进行兼容. — -i:

Socket调用Close后如何终止套接口的问题

setsockopt 设置 SO_LINGER 选项 此选项指定函数close对面向连接的协议如何操作(如TCP).内核缺省close操作是立即返回,如果有数据残留在套接口缓冲区中则系统将试着将这些数据发送给对方. SO_LINGER选项用来改变此缺省设置.使用如下结构: struct linger { int l_onoff; /* 0 = off, nozero = on */ int l_linger; /* linger time */ }; 有下列三种情况: 1.设置 l_onoff为

套接口学习(一)实现

套接口这个概念最先由4.2BSD(1983)引入,现在已经成为一个通用的网络应用程序编程接口,受到所有操作系统的支持.套接口层位于应用程序和 协议栈之间,对应用程序屏蔽了与协议相关实现的具体细节. 通常,应用程序中调用库函数,而库函数通过系统调用进入套接口层,Linux的套接口层实现提供了一组专门的套接口系统调用,分别在对应的库函数名之上加上"sys_"前缀.此外为了体现一切皆文件的理念,Linux也允许标准I/O系统调用通过一个套接口文件描述符来读写其对应套接口上的网络连接,就像通过

套接口编程简介

1.套接口地址结构 POSIX规范只需要结构中的三个成员:sin_family.sin_addr.sin_port.其中sin_addr又是一个结构 2.通用套接口地址结构 套接口函数被定义为采用指向通用套接口地址结构的指针.由于套接口函数的定义并没有使用void*指针类型, 所以调用套接口函数时必须进行强制类型转换. 使用通用套接口地址结构的原因:内核必须依据通用套接口地址结,检查sin_family的值来确定结构的类型 3.字节排序函数 多字节数据在内存中存储有两种方法.小端字节序把低字节存

高级套接口-(sendmsg和recvmsg)

Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类). 那么,如果我们要把"属性"(property)和"方法"(method),封装成一个对象,甚至要从原型对象生成一个实例对象,我们应该怎么做呢? 一. 生成对象的原始模式 假定我们把猫看成一个对象,它有"名字"和"颜色"两个属性. var C

C网络编程-TCP套接口编程

只有几个基本的示例如下 建立服务端的绑定监听等过程的函数 1 #include<sys/types.h> 2 #include<sys/socket.h> 3 4 #include<netinet/in.h> 5 #include<arpa/inet.h> 6 #include<unistd.h> 7 8 #include<stdio.h> 9 #include<stdlib.h> 10 11 #include<st

unix网络编程之基本套接口编程

第一章  套接口编程简介 IPv4套接口地址:"网际套接口地址结构" 通用套接口地址结构: 套接口函数被定义为采用指向通用套接口地址结构的指针,这要求对这些函数的任何调用都必须将指向特定于协议的套接口地址结构的指针类型转换成指向通用套接口地址结构的指针: 套接口地址结构的比较: 值-结果参数: 当把套接口地址结构传递给套接口函数时,总是通过指针来传递的,即传递的是一个指向结构的指针. 1, 从进程到内核传递套接口地址结构有3个函数:bind.connect.sendto,这3个函数的一

UNPv1第四章:基本TCP套接口编程

1 socket函数 为了执行网络I/O,一个进程必须做的第一件事就是调用socket函数,指定期望的通信协议类型 #include <sys/socket.h> int socket (int family, int type, int protocol); //返回:若成功则为非负描述符,若出错则为-1 其中family指明协议族,type参数指明套接字类型,protocol参数应该设为某个(见下图)协议类型常值,或者设为0,以选择所给定family和type组合的系统默认值 socket

什么是套接口?

什么是套接口?socket.套接口.套接口描述符之间的关系 UNP 的译者在 p6 中的译注中提到:socket 一词应该译成“套接口”,理由如下:首先,作为网络编程 API 之一的套接口(sockets.注意这种用法总是采用复数形式,例如 sockets API.sockets library)跟 XTI 一样,是应用层到传输层或其他协议层的访问接口.其次,具体使用的套接口时与 unix 管道的某一端类似的东西,我们既可以往这个“口”写数据,也可以从这个“口”读取数据.最后,套接口函数使用套接