TCP的异常释放和SO_LINGER套接字选项

1.TCP的异常关闭

正常终止一个连接的方法是发送一个FIN报文。有时也称为有序释放,因为所有排队数据都发送完之后才发送FIN,正常情况下没有任何数据的丢失。但也可能发送一个复位报文段而不是FIN来释放一个连接。有时称这位异常释放(abortive release)。

异常终止一个连接对应用程序来说有两个优点:

  1. 丢弃任何待发送数据并立即发送复位报文段
  2. RST的接收方会区分另一端执行的是异常关闭还是正常关闭。

应用程序使用的API必须提供产生异常关闭而不是正常关闭的手段。

Socket API通过"linger on close"选项(SO_LINGER)提供了这种异常关闭能力。 

2. SO_LINGER套接字选项

SO_LINGER选项用于控制close系统调用在关闭TCP连接时的行为。默认情况下,当我们使用close系统调用来关闭一个socket时,close将立即返回,TCP模块负责把该socket对应的TCP发送缓冲区中残留的数据发送给对方。

设置(获取)SO_LINGER选项的值时,我们需要给setsockopt(getsockopt)系统调用传递一个linger类型的结构体,其定义如下:

#include <sys/socket.h>
struct linger
{
    int l_onoff;// 开启(非0)还是关闭(0)该选项
    int l_linger;// 滞留时间
};

根据linger结构体中两个成员变量的不同值,close系统调用可能产生如下3种行为之一:

  1. l_onoff等于0(关闭)。此时SO_LINGER选项不起作用,close用默认行为来关闭socket。
  2. l_onoff不为0(开启),l_linger等于0。此时close系统调用立即返回,TCP模块将丢弃被关闭的socket对应的TCP发送缓冲区中残留的数据,同时给对方发送一个复位报文段(RST)。因此,这种情况给服务器提供了异常终止一个连接的方法。
  3. l_onoff不为0(开启),l_linger大于0。此时close的行为取决于两个条件:一是被关闭的socket对应的TCP发送缓冲区是否还有残留的数据;二是该socket是阻塞的,还是非阻塞的。对于阻塞的socket,close将等待一段长为l_linger的时间,直到TCP模块发送完所有残留数据并得到对方的确认。如果这段时间内TCP模块没有发送完残留数据并得到对方的确认,那么close系统调用将返回-1并设置errno为EWOULDBLOCK。如果socket是非阻塞的,close将立即返回,此时我们需要根据其返回值和errno来判断残留数据是否已经发送完毕。
发布了140 篇原创文章 · 获赞 65 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/paradox_1_0/article/details/103494382
今日推荐