socket编程选项——setsockopt和getsockopt

来源:互联网 发布:linux中查看最后几行 编辑:程序博客网 时间:2024/05/23 00:22

头文件:

#include <sys/types.h>  #include <sys/socket.h>  

setsockopt

函数原型:

int setsockopt(int sockfd, int level, int optname, const void* optival, socklen_t optlen);  

功能:

  用于任意类型、任意状态套接口的设置选项值.

参数:

  sockfd:标识一个套接口的描述字;    level:选项定义的层次;支持SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6;    optname:需设置的选项;    optval:指针,指向存放选项待设置的新值的缓冲区;    optlen:optval缓冲区长度;  

返回值:

  若无错误发生,setsockopt()返回0。
  否则返回SOCKET_ERROR(-1)错误,应用程序可通过WSAGetLastError()获取相应错误代码。

getsockopt

函数原型:

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

功能:

  用于获取任意类型、任意状态套接口的选项当前值,并将结果存入optval.

参数:

  sockfd:标识一个套接口的描述字;    level:选项定义的层次;支持SOL_SOCKET、IPPROTO_TCP;    optname:需获取的套接口选项;    optval:指针,指向存放所获得选项值的缓冲区;    optlen:指针,指向optval缓冲区的长度值;  

返回值:

  若无错误发生,getsockopt()返回0。
  否则返回SOCKET_ERROR(-1)错误,应用程序可通过WSAGetLastError()获取相应错误代码。

当level为SOL_SOCKET时,比较常用到的设置选项如下:

  • SO_ RCVBUF和SO_SNDBUF:
    用于设置/读取发送缓冲区和接收缓冲区大小
    选项值类型:int
    指定新的缓冲区大小,对setsockopt和getsockopt有效;
    说明:
      设置缓冲区大小只能在TCP连接建立之前进行.
      TCP将接收缓冲区大小用于流量控制
      UDP不提供流量控制,UDP没有实际的发送缓冲区,设置发送缓冲区的大小将改变能发送的最大UDP数据报的大小,使用如下:
      
int rcv_buf_size = 32 * 1024,snd_buf_size = 32 * 1024;  setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcv_buf_size,                   sizeof(int));  setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &SND_buf_size,        sizeof(int));   
  • 2.SO_REUSEADDR: 用于复用socket地址(端口号)。
    选项值类型:int,
    0—不能复用,1—可以复用
    默认值为0,对setsockopt和getsockopt有效;
    复用地址一般用于下列情况:
      a. 快速启动服务器:服务器在有客户端连接时终止,然后立即重启,由于TIME_WAIT状态的存在,会导致原来的socket依然存在,bind操作将失败,如果指定了SO_REUSEADDR选项可以避免这个问题;
       b. 启动一个服务程序的多个实例:当使用IP别名的时候,可以将若干个服务程序使用不同IP绑定到同一端口上;
      c. 多个socket绑定同一端口:用于UDP程序在有多个网络接口时,为了区分数据报来自哪一个网络接口而使用;
      实例代码:
int opt=1;  setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt,       sizeof(int));   


  • 3.SO_KEEPALIVE: 用于TCPsocket检测/保持网络连接。

这个选项被设置后,2小时以内双方没有数据交互,将发送一个探测数据段到对方,此时可能出现以下情况:
   a. 得到对方正确响应,继续等待下一次2小时超时;
   b. 收到RST数据段,返回错误ECONNRESET;
   c. 对方无响应,多次发送探测数据段直到超市返回错误ETIMEOUT;
   d. 选项值类型:int,0—不能发送;1—可以发送,默认值为0;
   对setsockopt和getsockopt有效;
int opt=1; setsockopt(sockfd,SOL_SOCKET,SO_KEEPALIVE,&opt,sizeof(int));  


  • 4.SO_LINGER: 用于设定close函数的操作方式.

选项值类型:
    struct linger{           int l_onoff; //选项是否有效           int l_linger; //关闭socket的延迟时间         };  

可能的情况:
1、l_onoff=0
  此时l_linger被忽略,close按默认方式工作;
2、l_onoff非0,l_linger=0
  close函数放弃连接向对方发送RST数据段,然后立即关闭socket,释放socket资源,这种情况socket不会进入TIME_WAIT状态,可能会导致以下的问题:
   a. 数据丢失(TCP协议丢弃未发送的数据);
   b. 连接非正常关闭(调用close的一方发送RST数据段,而不是FIN数据段,导致另一方认为发生错误,非正常关闭连接);
  c. 数据混乱(连接双方都不进入TIME_WAIT状态,因此在上次连接的数据没有从网络上消除之前,新的相同连接(IP和端口相同)可以建立,有可能会收到上次连接的数据,导致数据混乱).
3、 l_onoff和l_linger都非0
  close函数阻塞,在延迟指定的时间后关闭连接,根据数据是否在延时期间内得到确认正常返回或返回错误EWOULDBLOCK;

对setsockopt和getsockopt有效;

close函数只能保证数据被TCP协议正确接收,不能保证被应用程序正确接收,为了保证数据被对方应用程序接收,采用shutdown关闭写通道,继续读操作直到read函数返回0,调用close关闭连接。或者采用应用程序确认的方法实现;

 struct linger linger_opt;   linger_opt.l_onoff=1; linger_opt.l_linger=1000;          setsockopt(sockfd,SOL_SOCKET,SO_LINGER,&linger_opt,sizeof(linger_opt));  

当level为IPPROTO_TCP时,比较常用到的设置选项如下:

    1.TCP_MAXSEG:获取和设置一个TCP连接的最大数据段的大小;      2.TCP_NODELAY:用于禁止TCP协议的Nagle算法,使小数据包(小于最大数据段大小)立即发送,会降低TCP协议的效率   
0 0