您的位置:首页 > 运维架构

setsockopt和getsockopt函数解析

2016-04-11 21:59 543 查看
setsockopt和getsockopt函数解析:

头文件:#include <sys/types.h>   #include <sys/socket.h>

函数原型:
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()获取相应错误代码。

函数原型:
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时,比较常用到的设置选项如下:
    1.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的延迟时间
 };
 可能的情况:
 l_onoff=0,此时l_linger被忽略,close按默认方式工作;
 l_onoff非0,l_linger=0,close函数放弃连接向对方发送RST数据段,然后立即关闭socket,释放socket资源,这种情况socket不会进入TIME_WAIT状态,可能会导致以下的问题:
 a. 数据丢失(TCP协议丢弃未发送的数据);
 b. 连接非正常关闭(调用close的一方发送RST数据段,而不是FIN数据段,导致另一方认为发生错误,非正常关闭连接);
 c. 数据混乱(连接双方都不进入TIME_WAIT状态,因此在上次连接的数据没有从网络上消除之前,新的相同连接(IP和端口相同)可以建立,有可能会收到上次连接的数据,导致数据混乱).
 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协议的效率
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: