zoukankan      html  css  js  c++  java
  • 套接口选项

    设置和影响套接口选项的方法有
    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
  • 相关阅读:
    Window 窗口类
    使用 Bolt 实现 GridView 表格控件
    lua的table库
    Windows编程总结之 DLL
    lua 打印 table 拷贝table
    使用 xlue 实现简单 listbox 控件
    使用 xlue 实现 tips
    extern “C”
    COleVariant如何转换为int double string cstring
    原来WIN32 API也有GetOpenFileName函数
  • 原文地址:https://www.cnblogs.com/learn-my-life/p/5660899.html
Copyright © 2011-2022 走看看