SOCKET选项-阿里云开发者社区

开发者社区> 黄智杰> 正文

SOCKET选项

简介: 在了解SOCKET选项之前请先了解TCP/IP协议的基本知识,如三次握手,四次挥手,11种状态之间是如何迁移,调用socket各个API会让TCP层进行什么操作等。API头文件: sys/socket.
+关注继续查看

在了解SOCKET选项之前请先了解TCP/IP协议的基本知识,如三次握手,四次挥手,11种状态之间是如何迁移,调用socket各个API会让TCP层进行什么操作等。
API头文件: sys/socket.h>
获取指定socket连接的选项
int getsockopt(int sock, int level, int optname, void optval, socklen_t optlen);
设置指定socket连接的选项
int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);

example:

int sockfd = socket(AF_INET,SOCK_STREAM,0);
int recvbuf = 0;
int len = sizeof( recvbuf );
getsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&len);
printf("old recvbuf = %d",recvbuf);
  
recvbuf = 1024*30;
if(0 != setsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof( recvbuf) ))
{
  printf("setsockopt SO_RCVBUF error“);
}

使用setsockopt()的时间:服务器要求在listen()之前,客户端要求在connect()之前,因为有些选项诸如SO_RCVBUF的信息,是包含在三次握手中,因此必须在三次握手前完成设置,服务器端accept产生的socket连接,会自动继承listen前设置的大部分选项,如SO_LINGER、SO_SNFBUF、SO_RCVBUF。

参数:
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获得或者是设置套接字选项的值。

常用的Socket中SOL_SOCKET有以下几个重要的optname选项。

SO_RESUSEADDR:表示是否允许重用Socket所绑定的本地地址
SO_LINGER:表示当执行Socket的close()方法时,是否立即关闭底层的Socket
SO_SNFBUF:表示发送数据的缓冲区大小
SO_RCVBUF:表示接受数据的缓冲区大小

必知必会的选项:
1.SO_REUSEADDR
服务器可以设置该选项来强制使用处于TIME_WAIT状态的socket地址。如果有两个进程,第一个进程的socket处于TIME_WAIT状态,第二个进程要使用同样的地址和端口,只需要第二个进程的socket有设置该选项即可。

应用场景:如果服务器主动关闭了应用,没有设置该选项,重启服务器的该应用,会出现失败,无法绑定端口,因为端口还没有释放。需要等待2MSL时间后才能重新绑定,一般情况下是2-4分钟。

SO_REUSEADDR滥用容易引发bug,UNP1经典书籍列举了只有以下四种情况适用该选项:
1.当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。另外作为服务daemon一般都会使用SO_REUSEADDR,避免服务意外崩溃而原有socket还未被kernel释放时,重启的daemon仍然可以bind成功。
2.SO_REUSEADDR允许同一port上启动同一服务器的多个实例。但每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可以测试这种情况。
3.SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上,但每个socket绑定的ip地址不同。这和2很相似,区别请看UNPv1。
4.SO_REUSEADDR允许完全相同的地址和端口的重复绑定。但这只用于UDP的多播,不用于TCP。

有一个滥用该选项导致的异常例子,http://blog.chinaunix.net/uid-23629988-id-217123.html

2.SO_LINGER:
此选项指定函数close对面向连接的协议如何操作(如TCP),内核缺省close操作是将立即返回,如果有数据残留在套接口缓冲区中则系统将试着将这些数据发送给对方。close函数是将当前的fd引用数减1,如果引用数已经为0,则在发送队列的末尾插入FIN标志,给对端发送FIN报文段。

选项中需要用到的结构体如下

struct linger
{ 
int l_onoff //0=off, nonzero=on(开关) 
int l_linger //linger time(延迟时间) 
} 

example:

int sockfd = socket(AF_INET,SOCK_STREAM,0);
struct linger so_linger;
so_linger.l_onoff = TRUE;
so_linger.l_linger = 30;
if(0 != setsockopt(sockfd,SOL_SOCKET,SO_LINGER,&so_linger,sizeof (so_linger)))
{
  printf("setsockopt SO_LINGER error“);
}

1:默认设置
默认状态下l_onoff==0,此时忽略l_linger,调用closesocket()会将FIN包放到队列末尾,然后函数返回
效果是TCP会将队列残留的数据发完,然后发送FIN,执行四次挥手。

2:l_onoff!=0&&l_linger==0
调用closesocket(),会清空未发队列的数据,然后投递一个RST,函数返回,这避免了TIME_WAIT状态。

3:l_onoff!=0&&l_linger!=0
调用closesocket(),向队列投递一个FIN,设置一个计时器,大小为l_linger,单位为秒。

1:收到所有发送出去的数据和FIN的ACK时未超时:
函数返回,并执行四次挥手的剩余步骤。(当应用层调用close时候,实际上服务器已经处于close_wait状态,已经完成了四次挥手的前两个步骤

2:超时:
函数返回SOCKET_ERROR,WINDOW系统下,WSAGetLastError()返回EWOULDBLOCK,清空队列,在对方发送FIN后,发送RET

3:备注:
对于1所述情况,我们只能确定对方TCP已经收到数据,但无法确定对方进程是否已经收到数据。
因为对端接受到FIN后,TCP层会回发一个应答报文,对端从FIN_WAIT1状态迁移到TIME_WAIT状态,在2MSL后,从TIME_WAIT状态迁移到CLOSED状态。这一部分工作都是TCP在自动执行,不需要上层进程操作,所以我们无法确定对方进程是否已经收到数据。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
网易的工程师文化和微服务演进
导读:第七届TOP100全球软件案例研究峰会将于11月30日-12月3日在北京国家会议中心举办,本届峰会以“释放AI生产力 让组织向智能化演进”为开幕式主题,旨在推动企业在趋势下拥抱AI、探索和思考AI带来的力量。十八个主题专场,120个案例为组织形式,意在向参会者解读2018年软件研发设计创新案例。 会前TOP100组委会专访案例分享者网易杭州研究院云计算部门张小刚老师,他将为我们带来《网易的工程师文化和微服务演进》的话题 。讲述网易在微服务面的一些实践和感悟。
3 0
i人事CTO王景飞:i人事+计算巢,协同赋能HR业务
借助计算巢平台将整个安全链路所需集合成一个完整的解决方案。
4 0
Keras之父写给年轻程序员的33条忠告
  代码是一种交流方式,Keras 之父 Fran?ois Chollet 在本文中为我们总结了在开发过程中、API 设计中及软件职业生涯中应该关注哪些要点。原则是形式化的直觉,比原始模式识别适用于更广泛的情况,Fran?ois Chollet 的这份原则清单将带你领略大师的品味。
3 0
+关注
3
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载