zoukankan      html  css  js  c++  java
  • setsockopt角色

    功能描写叙述:

            获取或者设置与某个套接字关联的选 项。

    选项可能存在于多层协议中。它们总会出如今最上面的套接字层。

    当操作套接字选项时。选项位于的层和选项的名称必须给出。为了操作套接字层的选项,应该 将层的值指定为SOL_SOCKET。为了操作其他层的选项,控制选项的合适协议号必须给出。比如,为了表示一个选项由TCP协议解析,层应该设定为协议 号TCP。




    使用方法:
    #include <sys/types.h>
    #include <sys/socket.h>


    int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);


    int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);


    參数:  
    sock:将要被设置或者获取选项的套接字。
    level:选项所在的协议层。
    optname:须要訪问的选项名。


    optval:对于getsockopt(),指向返回选项值的缓冲。

    对于setsockopt()。指向包括新选项值的缓冲。


    optlen:对于getsockopt(),作为入口參数时,选项值的最大长度。作为出口參数时,选项值的实际长度。

    对于setsockopt(),现选项的长度。






    返回说明:  




    成功运行时,返回0。失败返回-1,errno被设为下面的某个值  
    EBADF:sock不是有效的文件描写叙述词
    EFAULT:optval指向的内存并不是有效的进程空间
    EINVAL:在调用setsockopt()时,optlen无效
    ENOPROTOOPT:指定的协议层不能识别选项
    ENOTSOCK:sock描写叙述的不是套接字




    參数具体说明:


    level指定控制套接字的层次.能够取三种值:
    1)SOL_SOCKET:通用套接字选项.
    2)IPPROTO_IP:IP选项.
    3)IPPROTO_TCP:TCP选项. 
    optname指定控制的方式(选项的名称),我们以下详解 


    optval获得或者是设置套接字选项.依据选项名称的数据类型进行转换 




    选项名称        说明                  数据类型
    ========================================================================
                SOL_SOCKET
    ------------------------------------------------------------------------
    SO_BROADCAST      同意发送广播数据            int
    SO_DEBUG        同意调试                int
    SO_DONTROUTE      不查找路由               int
    SO_ERROR        获得套接字错误             int
    SO_KEEPALIVE      保持连接                int
    SO_LINGER        延迟关闭连接              struct linger
    SO_OOBINLINE      带外数据放入正常数据流         int
    SO_RCVBUF        接收缓冲区大小             int
    SO_SNDBUF        发送缓冲区大小             int
    SO_RCVLOWAT       接收缓冲区下限             int
    SO_SNDLOWAT       发送缓冲区下限             int
    SO_RCVTIMEO       接收超时                struct timeval
    SO_SNDTIMEO       发送超时                struct timeval
    SO_REUSERADDR      同意重用本地地址和port         int
    SO_TYPE         获得套接字类型             int
    SO_BSDCOMPAT      与BSD系统兼容              int
    ========================================================================
                IPPROTO_IP
    ------------------------------------------------------------------------
    IP_HDRINCL       在数据包中包括IP首部          int
    IP_OPTINOS       IP首部选项               int
    IP_TOS         服务类型
    IP_TTL         生存时间                int
    ========================================================================
                IPPRO_TCP
    ------------------------------------------------------------------------
    TCP_MAXSEG       TCP最大数据段的大小           int
    TCP_NODELAY       不使用Nagle算法             int
    ========================================================================


    返回说明:  
    成功运行时,返回0。失败返回-1,errno被设为下面的某个值  
    EBADF:sock不是有效的文件描写叙述词
    EFAULT:optval指向的内存并不是有效的进程空间
    EINVAL:在调用setsockopt()时。optlen无效
    ENOPROTOOPT:指定的协议层不能识别选项
    ENOTSOCK:sock描写叙述的不是套接字


    SO_RCVBUF和SO_SNDBUF每一个套接口都有一个发送缓冲区和一个接收缓冲区,使用这两个套接口选项能够改变缺省缓冲区大小。




    // 接收缓冲区
    int nRecvBuf=32*1024;         //设置为32K
    setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));




    //发送缓冲区
    int nSendBuf=32*1024;//设置为32K
    setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int));


    注意:


            当设置TCP套接口接收缓冲区的大小时,函数调用顺序是非常重要的,由于TCP的窗体规模选项是在建立连接时用SYN与对方互换得到的。

    对于客户,O_RCVBUF选项必须在connect之前设置;对于server,SO_RCVBUF选项必须在listen前设置。


    结合原理说明:


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

    接收缓冲区被TCP和UDP用来将接收到的数据一直保存到由应用进程来读。

    TCP:TCP通告还有一端的窗体大小。 TCP套接口接收缓冲区不可能溢出。由于对方不同意发出超过所通告窗体大小的数据。

    这就是TCP的流量控制,假设对方无视窗体大小而发出了超过窗体大小的数据。则接 收方TCP将丢弃它。

    UDP:当接收到的数据报装不进套接口接收缓冲区时。此数据报就被丢弃。

    UDP是没有流量控制的;快的发送者能够非常easy地就淹没慢的接收者。导致接收方的UDP丢弃数据报。


            2.我们常常听说tcp协议的三次握手,但三次握手究竟是什么。其细节是什么,为什么要这么做呢?


            第一次:client发送连接请求给server。server接收;
            第二次:server返回给client一个确认码,附带一个从server到client的连接请求,客户机接收,确认client到server的连接.
            第三次:客户机返回server上次发送请求的确认码,server接收,确认server到client的连接.
            我们能够看到:
            1. tcp的每一个连接都须要确认.
            2. client到server和server到client的连接是独立的.
            我们再想想tcp协议的特点:连接的,可靠的,全双工的,实际上tcp的三次握手正是为了保证这些特性的实现.




            3.setsockopt的使用方法


    1.closesocket(一般不会马上关闭而经历TIME_WAIT的过程)后想继续重用该socket:
    BOOL bReuseaddr=TRUE;
    setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL));




    2. 假设要已经处于连接状态的soket在调用closesocket后强制关闭。不经历TIME_WAIT的过程:
    BOOL bDontLinger = FALSE;
    setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*)&bDontLinger,sizeof(BOOL));




    3.在send(),recv()过程中有时因为网络状况等原因,发收不能预期进行,而设置收发时限:
    int nNetTimeout=1000;//1秒
    //发送时限
    setsockopt(socket,SOL_S0CKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int));
    //接收时限
    setsockopt(socket。SOL_S0CKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int));




    4.在send()的时候。返回的是实际发送出去的字节(同步)或发送到socket缓冲区的字节
    (异步);系统默认的状态发送和接收一次为8688字节(约为8.5K)。在实际的过程中发送数据
    和接收数据量比較大,能够设置socket缓冲区,而避免了send(),recv()不断的循环收发:
    // 接收缓冲区
    int nRecvBuf=32*1024;//设置为32K
    setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
    //发送缓冲区
    int nSendBuf=32*1024;//设置为32K
    setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int));




    5. 假设在发送数据的时。希望不经历由系统缓冲区到socket缓冲区的拷贝而影响
    程序的性能:
    int nZero=0;
    setsockopt(socket,SOL_S0CKET,SO_SNDBUF,(char *)&nZero,sizeof(nZero));




    6.同上在recv()完毕上述功能(默认情况是将socket缓冲区的内容复制到系统缓冲区):
    int nZero=0;
    setsockopt(socket。SOL_S0CKET,SO_RCVBUF,(char *)&nZero,sizeof(int));




    7.一般在发送UDP数据报的时候,希望该socket发送的数据具有广播特性:
    BOOL bBroadcast=TRUE;
    setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*)&bBroadcast,sizeof(BOOL));




    8.在client连接server过程中,假设处于非堵塞模式下的socket在connect()的过程中能够设置connect()延时,直到accpet()被呼叫(本函数设置仅仅有在非堵塞的过程中有显著的作用,在堵塞的函数调用中作用不大)
    BOOL bConditionalAccept=TRUE;
    setsockopt(s,SOL_SOCKET,SO_CONDITIONAL_ACCEPT,(const char*)&bConditionalAccept,sizeof(BOOL));




    9.假设在发送数据的过程中(send()没有完毕,还有数据没发送)而调用了closesocket(),曾经我们一般採取的措施是"从容关闭"shutdown(s,SD_BOTH),可是数据是肯定丢失了,怎样设置让程序满足详细应用的要求(即让没发完的数据发送出去后在关闭socket)?
    struct linger {
    u_short l_onoff;
    u_short l_linger;
    };
    linger m_sLinger;
    m_sLinger.l_onoff=1;//(在closesocket()调用,可是还有数据没发送完成的时候容许逗留)
    // 假设m_sLinger.l_onoff=0;则功能和2.)作用同样;
    m_sLinger.l_linger=5;//(容许逗留的时间为5秒)
    setsockopt(s,SOL_SOCKET,SO_LINGER,(const char*)&m_sLinger,sizeof(linger));

  • 相关阅读:
    康复计划
    Leetcode 08.02 迷路的机器人 缓存加回溯
    Leetcode 38 外观数列
    Leetcode 801 使序列递增的最小交换次数
    Leetcode 1143 最长公共子序列
    Leetcode 11 盛水最多的容器 贪心算法
    Leetcode 1186 删除一次得到子数组最大和
    Leetcode 300 最长上升子序列
    Leetcode95 不同的二叉搜索树II 精致的分治
    Leetcode 1367 二叉树中的列表 DFS
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4593589.html
Copyright © 2011-2022 走看看