setsockopt 设置 SO_LINGER 选项

此选项指定函数close对面向连接的协议如何操作(如TCP)。内核缺省close操作是立即返回,如果有数据残留在套接口缓冲区中则系统将试着将这些数据发送给对方。

SO_LINGER选项用来改变此缺省设置。使用如下结构:

struct linger {

int l_onoff; /* 0 = off, nozero = on */

int l_linger; /* linger time */

};

有下列三种情况:

1、设置 l_onoff为0,则该选项关闭,l_linger的值被忽略,等于内核缺省情况,close调用会立即返回给调用者,如果可能将会传输任何未发送的数据;

2、设置 l_onoff为非0,l_linger为0,则套接口关闭时TCP夭折连接,TCP将丢弃保留在套接口发送缓冲区中的任何数据并发送一个RST给对方,而不是通常的四分组终止序列,这避免了TIME_WAIT状态;

3、设置 l_onoff 为非0,l_linger为非0,当套接口关闭时内核将拖延一段时间(由l_linger决定)。如果套接口缓冲区中仍残留数据,进程将处于睡眠状态,直 到(a)所有数据发送完且被对方确认,之后进行正常的终止序列(描述字访问计数为0)或(b)延迟时间到。此种情况下,应用程序检查close的返回值是非常重要的,如果在数据发送完并被确认前时间到,close将返回EWOULDBLOCK错误且套接口发送缓冲区中的任何数据都丢失。close的成功返回仅告诉我们发送的数据(和FIN)已由对方TCP确认,它并不能告诉我们对方应用进程是否已读了数据。如果套接口设为非阻塞的,它将不等待close完成。

注释:l_linger的单位依赖于实现: 4.4BSD假设其单位是时钟滴答(百分之一秒),但Posix.1g规定单位为秒。

下面的代码是一个使用SO_LINGER选项的例子,使用30秒的超时时限:
#define TRUE     1
#define FALSE    0
int z; /* Status code
*/ int s;       /* Socket s */
struct linger so_linger;
...
so_linger.l_onoff = TRUE;
so_linger.l_linger = 30;
z = setsockopt(s,
    SOL_SOCKET,
    SO_LINGER,
    &so_linger,
    sizeof so_linger);
if ( z )
   perror("setsockopt(2)");

下面的例子显示了如何设置SO_LINGER的值来中止套接口s上的当前连接:
#define TRUE     1
#define FALSE    0
int z; /* Status code */
int s;       /* Socket s */
struct linger so_linger;
...
so_linger.l_onoff = TRUE;
so_linger.l_linger = 0;
z = setsockopt(s,
    SOL_SOCKET,
    SO_LINGER,
    &so_linger,
    sizeof so_linger);
if ( z )
    perror("setsockopt(2)");
    close(s); /* Abort connection */

在上面的这个例子中,当调用close函数时,套接口s会立即中止。中止的语义是通过将超时值设置为0来实现的。

/********** WINDOWS **********/

/* 当连接中断时,需要延迟关闭(linger)以保证所有数据都被传输,所以需要打开SO_LINGER这个选项;  
 * //注:大致意思就是说SO_LINGER选项用来设置当调用closesocket时是否马上关闭socket; 
 * linger的结构在/usr/include/linux/socket.h中定义://注:这个结构就是SetSocketOpt中的Data的数据结构 
 *  struct linger 
 *  { 
 *   int l_onoff;  /* Linger active */       //低字节,0和非0,用来表示是否延时关闭socket
 *   int l_linger; /* How long to linger */   //高字节,延时的时间数,单位为秒
 *  }; 
 *  如果l_onoff为0,则延迟关闭特性就被取消。

*   如果非零,则允许套接口延迟关闭; l_linger字段则指明延迟关闭的时间 
 */

更具体的描述如下:
1、若设置了SO_LINGER(亦即linger结构中的l_onoff域设为非零),并设置了零超时间隔,则closesocket()不被阻塞立即执行,不论是否有排队数据未发送或未被确认。这种关闭方式称为“强制”或“失效”关闭,因为套接口的虚电路立即被复位,且丢失了未发送的数据。在远端的recv()调用将以WSAECONNRESET出错。

2、若设置了SO_LINGER并确定了非零的超时间隔,则closesocket()调用阻塞进程,直到所剩数据发送完毕或超时。这种关闭称为“优雅”或“从容”关闭。请注意如果套接口置为非阻塞且SO_LINGER设为非零超时,则closesocket()调用将以WSAEWOULDBLOCK错误返回。

3、若在一个流类套接口上设置了SO_DONTLINGER(也就是说将linger结构的l_onoff域设为零),则closesocket()调用立即返回。但是,如果可能,排队的数据将在套接口关闭前发送。请注意,在这种情况下WINDOWS套接口实现将在一段不确定的时间内保留套接口以及其他资源,这对于想用所以套接口的应用程序来说有一定影响。

SO_DONTLINGER 若为真,则SO_LINGER选项被禁止。
SO_LINGER延迟关闭连接 struct linger上面这两个选项影响close行为;

选项          间隔    关闭方式  等待关闭与否
  SO_DONTLINGER   不关心     优雅         否
  SO_LINGER        零        强制         否
  SO_LINGER       非零       优雅         是

Socket调用Close后如何终止套接口的问题的更多相关文章

  1. socket , 套接口还是套接字,傻傻分不清楚

    socket 做网络通信的朋友大都对socket这个词不会感到陌生,但是它的中文翻译是叫套接口还是套接字呢,未必大多数朋友能够分清,今天我们就来聊聊socket的中文名称. socket一词的起源 在 ...

  2. UNIX网络编程读书笔记:基本TCP套接口编程

    编写一个完整的TCP客户和服务器程序所需要的基本套接口函数: 1.socket函数(客户端.服务器端都必须调用) 参数family指明协议族(family),该参数也往往被称为协议域(domain). ...

  3. 值得收藏的TCP套接口编程文章

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由jackieluo发表于云+社区专栏 TCP客户端-服务器典型事件 下图是TCP客户端与服务器之间交互的一系列典型事件时间表: 首先启 ...

  4. 套接口socket编程(Client/Server编程实例)

    基本概念 套接口也就是网络中的ID.网络通信,归根到底还是进程间通信(不同计算机上的进程间的通信).在网络中,每一个节点(计算机或路由器)都有一个网络地址,也就是IP地址. IP地址:在网络中唯一标识 ...

  5. UDP套接口编程

    常用的UDP实现的程序:DNS域名系统,NFS网络文件系统,SNMP简单网络管理协议 ssize_t recvfrom(int sockfd,void *buff,size_t nbytes,int ...

  6. UNIX网络编程读书笔记:基本UDP套接口编程

    概述 使用UDP编写的一些流行的应用程序有:DNS(域名系统).NFS(网络文件系统)和SNMP(简单网络管理协议). 如下图所示,给出了典型的UDP客户/服务器程序的函数调用: 客户不与服务器建立连 ...

  7. UNIX网络编程读书笔记:套接口选项

    概述 有很多方法来获取和设置影响套接口的选项: getsockopt和setsockopt函数 fcntl函数 ioctl函数 getsockopt和setsockopt函数 这两个函数仅用于套接口. ...

  8. 设置套接口的选项setsockopt的用法

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  9. UNIX网络编程读书笔记:原始套接口

    概述 应用程序可以绕过传输层而直接使用IPv4和IPv6,这称为原始套接口(raw socket).http://www.cnblogs.com/nufangrensheng/p/3583435.ht ...

随机推荐

  1. 20155219&20155224 《信息安全系统设计基础》实验一 开发环境的熟悉

    实验内容 实验两人一组,最多三人一组 可以使用自己的笔记本,也可以使用实验室台式机 使用实验箱作为超级终端. 实验中学到的知识点 交叉编译 宿主机与目标机 NFS 超级终端 file命令 实验步骤 实 ...

  2. xdoj-1279(有趣的线段树--吉司机?!)

    题目链接 一 核心: f(x)=91 (x<=100) f(x)=x-10 (x>100) 那么同一区间就可能不同的操作,那么该怎么解决呢? 我门直到同一区间的数据属于同一类别的时候再进行 ...

  3. this语句的第三、四点

    接着上次的继续更新  up~` 第三点主体怎么找? 就在这个函数(方法)带不带“.”,如果函数和方法执行带“.”,那么this就指向“.”前面的对象,如果不带“.”就指向window. 第四点自执行函 ...

  4. 2018.4.23 深入理解java虚拟机(转)

    深入理解java虚拟机 精华总结(面试) 一.运行时数据区域 Java虚拟机管理的内存包括几个运行时数据内存:方法区.虚拟机栈.本地方法栈.堆.程序计数器,其中方法区和堆是由线程共享的数据区,其他几个 ...

  5. Android 播放内部mp3音乐

    private void heartSound() { try { AssetManager am = getAssets();//获得该应用的AssetManager AssetFileDescri ...

  6. Eclipse使用Maven时出现:Index downloads are disabled, search results may be incomplete.问题解决

    https://www.cnblogs.com/EasonJim/p/6674099.html 1.全局设置 [Windows]->[Preferences]->[Maven]->勾 ...

  7. nginx配置基于域名的虚拟主机

    其实基于域名和基于ip的虚拟主机配置是差不多的,在配置基于ip的虚拟主机上我们只需要修改几个地方就能变成基于域名的虚拟主机,一个是要修改域名,一个是host文件直接看代码 [root@localhos ...

  8. linux之nagios安装教程

    我的系统环境是centos7,其它系统应该也差不多,只是有几条命令可能需要换种写法 下面是我用到的命令 363 yum install -y gcc gcc-c++ httpd php php-gd ...

  9. 使用kompose 快速转换dokcer-compose 文件为k8s deploy 文件

    kompose 是一个不错的快速转换docker-compose 文件为k8s 部署yaml文件的工具,使用次工具我们 可以将简单的docker-compose文件,转换为复杂的yaml文件,对于使用 ...

  10. 【转载】Win10系统怎么清空剪切板?Win10系统清空剪切板的方法

    以下文转载至系统之家: 网址:http://www.xitongzhijia.net/xtjc/20190319/152585.html Win10系统怎么清空剪切板?Win10系统清空剪切板的方法 ...