Socket调用Close后如何终止套接口的问题

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       非零       优雅         是

时间: 2024-08-07 08:36:27

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

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

socket 做网络通信的朋友大都对socket这个词不会感到陌生,但是它的中文翻译是叫套接口还是套接字呢,未必大多数朋友能够分清,今天我们就来聊聊socket的中文名称. socket一词的起源 在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的,撰写者为Stephen Carr.Steve Crocker和Vint Cerf.根据美国计算机历史博物馆的记载,Croker写道:"命名空间的元素都可称为套接字接口.一个套接字接口构成一个连接的一端,而一个连接可完全

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

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由jackieluo发表于云+社区专栏 TCP客户端-服务器典型事件 下图是TCP客户端与服务器之间交互的一系列典型事件时间表: 首先启动服务器,等待客户端连接 启动客户端,连接到服务器 客户端发送一个请求给服务器,服务器处理请求,响应客户端 循环步骤3 客户端给服务器发一个文件结束符,关闭客户端连接 服务器也关闭连接 基本TCP客户-服务器程序的套接口函数 套接口编程基本函数 socket 函数 为了执行网络I/O,一个进程(无论

UNPv1第四章:基本TCP套接口编程

1 socket函数 为了执行网络I/O,一个进程必须做的第一件事就是调用socket函数,指定期望的通信协议类型 #include <sys/socket.h> int socket (int family, int type, int protocol); //返回:若成功则为非负描述符,若出错则为-1 其中family指明协议族,type参数指明套接字类型,protocol参数应该设为某个(见下图)协议类型常值,或者设为0,以选择所给定family和type组合的系统默认值 socket

套接口选项

设置和影响套接口选项的方法有 1.getsockopt和setsockopt 2.fcntl 3.ioctl getsockopt和setsockopt 这两个方法仅适用于套接字 有两种基本类型的套接口选项:打开或关闭某个特性的二进制标志,取得并返回我们可以设置或检验的特定值的选项,标有标志的列指明是否为标志选项,对于这些项,0表示关闭标志,非0表示打开标志. 并不是所有的系统的套接字都支持所有的选项,必要时候自行验证一番. 套接字的不支持分为两种 1.未实现相关的定义,比如SO_REUSEPO

套接口学习(一)实现

套接口这个概念最先由4.2BSD(1983)引入,现在已经成为一个通用的网络应用程序编程接口,受到所有操作系统的支持.套接口层位于应用程序和 协议栈之间,对应用程序屏蔽了与协议相关实现的具体细节. 通常,应用程序中调用库函数,而库函数通过系统调用进入套接口层,Linux的套接口层实现提供了一组专门的套接口系统调用,分别在对应的库函数名之上加上"sys_"前缀.此外为了体现一切皆文件的理念,Linux也允许标准I/O系统调用通过一个套接口文件描述符来读写其对应套接口上的网络连接,就像通过

unix网络编程之基本套接口编程

第一章  套接口编程简介 IPv4套接口地址:"网际套接口地址结构" 通用套接口地址结构: 套接口函数被定义为采用指向通用套接口地址结构的指针,这要求对这些函数的任何调用都必须将指向特定于协议的套接口地址结构的指针类型转换成指向通用套接口地址结构的指针: 套接口地址结构的比较: 值-结果参数: 当把套接口地址结构传递给套接口函数时,总是通过指针来传递的,即传递的是一个指向结构的指针. 1, 从进程到内核传递套接口地址结构有3个函数:bind.connect.sendto,这3个函数的一

什么是套接口?

什么是套接口?socket.套接口.套接口描述符之间的关系 UNP 的译者在 p6 中的译注中提到:socket 一词应该译成“套接口”,理由如下:首先,作为网络编程 API 之一的套接口(sockets.注意这种用法总是采用复数形式,例如 sockets API.sockets library)跟 XTI 一样,是应用层到传输层或其他协议层的访问接口.其次,具体使用的套接口时与 unix 管道的某一端类似的东西,我们既可以往这个“口”写数据,也可以从这个“口”读取数据.最后,套接口函数使用套接

【转】Linux C 网络编程——TCP套接口编程

地址:http://blog.csdn.net/matrix_laboratory/article/details/13669211 2. socket() [cpp] view plaincopy <span style="font-size:14px">int socket(int domain, int type, int protocol);</span> socket()打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符,应用程

常用socket调用函数

socket调用 功能描述 accept()* 响应连接请求并新建套接口,原来的套接口则返回监听状态(服务器用) bind() 把一个本地的名字和一个套接口捆绑起来 closesocket()* 把套接口从拥有对象参考表中取消.该函数只在so_linger被设置时才会阻塞 connect()* 与服务器建立连接(client端用) getpeername() 得到连接在指定套接口上的对等通讯方的名字 getsockname() 得到指定套接口上当前的名字 getsockopt() 得到与指定套接