TCP异常终止连接及SO_LINGER选项

TCP的SO_LINGER 选项 TCP的SO_LINGER 选项 一、TCP7次握手 TCP建立连接需要经过3次握手,断开连接需要经过4次握手。详细的过程,以及每一步状态见下图 二、2MSL TIME_WAIT状态也称为2MSL等待状态。每个具体TCP实现必须选择一个报文段最大生存时间MSL。它是任何报文段被丢弃前在网络内的最长时间(一般是1分钟或两分钟)。TCP报文段是以IP数据报在 阅读详情

TCP的异常终止连接及SO_LINGER选项:

终止一个连接的正常方式是一方发送FIN,进入FIN_WAIT1状态。当我们调用close()函数关闭连接之后,如果在发送缓冲区中还有数据,那么系统会发送这些数据,然后再发送FIN,但是也有可能发送一个复位报文段来释放一个连接,这种现象就称为异常终止连接。

异常终止一个连接有两个优点:(1.马上丢弃待发送数据并立即发送复位报文段(2.RST的接收方会区分另一端执行的是异常关闭还是正常关闭。

我们可以自己编写sock程序并使用tcpdump工具进行分析查看异常关闭的整个过程(sock代码放在最后)。

  1. 首先运行tcpdump "port 6666" -i lo -S(指定监听的端口,-i参数代表选择监听的网卡,lo是用来进行环回测试的,-S命令是完整的显示序号)
  2. 接下来运行我们编译完成的server端./server
  3. 再运行client端./client
  4. 这个时候就可以看到运行了tcpdump那个终端显示出了三次握手的三个报文
  5. 再启动一个终端运行netstat -ano | grep 6666,查看6666端口的使用情况
  6. ctrl+c终止任意一端,这时候查看运行了tcpdump那个终端显示的数据,就会发现多了一行数据,即复位报文段。再次运行netstat -ano | grep 6666,会发现已经没有进程占用6666端口了。这点和以前不同,正常的终止连接主动关闭方会进入TIME_WAIT状态,但是此时已经没有进程占用6666端口了,说明主动关闭方跳过了TIME_WAIT状态直接关闭了。

贴出测试图:
tcpdump命令显示的结果(前三个是tcp三次握手,最后一个是RST复位报文段):
这里写图片描述
netstat命令显示的结果:
这里写图片描述
异常关闭的实现是通过setsockopt()函数中的SO_LINGER选项实现的。前面我们提到在正常情况下主动关闭连接会把发送缓冲区中的数据都发送出去,但是并不知道对端的TCP是否确认了数据。而使用SO_LINGER选项,并将l_linger的值设置为大于0,那么就会在调用close()之后,close()不立即返回,而是等待l_linger秒,直到对端发送了对数据和FIN的确认之后,close()再成功返回,还有一种close()返回的情况,那就是过了l_linger秒之后,对端还没有发送对数据和FIN的确认,这时close()会返回-1并设置errno为EWOULDBLOCK。这里有很重要的一点就是,即使close成功返回了,但是并不代表对端应用程序是否已读取数据,只能说明对端确认了数据和FIN。
如果l_linger的值设置为0,那么就会造成上面我们进行实验的情况,立即关闭连接,跳过了TIME_WAIT状态。
SO_LINGER选项总的来说有四个方面需要注意:

  1. 进程会阻塞,直到状态不为FIN_WAIT1、CLOSING、LAST_ACK或者等待超时
  2. 在等待的过程中如果接收到带数据的包还是会发送复位报文段
  3. 消耗更多的额外资源
  4. 设置等待时间为0时,不会发送FIN报文段而是发送RST报文段直接关闭连接,不管缓冲区中有无数据。

server端代码(多线程处理):

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <pthread.h>

#define SERV_PORT 6666


void *deal(void *arg)
{
    int listenfd = (int )arg;
    printf("fd:%d\n", listenfd);
    while(1)
    {
        char msg[BUFSIZ];

        int n = read(listenfd, msg, BUFSIZ);
        int i = 0;
        for(; i < n; i++)
        {
            msg[i] = toupper(msg[i]);
        }

        write(listenfd, msg, n);
    }
    close(listenfd);
}
int main()
{
    struct sockaddr_in serv_addr, clie_addr;
    socklen_t len;
    int sockfd, listenfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    char msg[BUFSIZ];
    pthread_t pid;

    bzero(&serv_addr, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);
    inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr.s_addr);

    bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

    struct linger flag;
    flag.l_onoff = 1;       //l_onoff置1代表开启该选项
    flag.l_linger = 0;      //指定等待时间
    setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &flag, sizeof(flag));
    listen(sockfd, 5);
    printf("wait accepting......\n");
    int i = 0;
    while(1)
    {
        len = sizeof(clie_addr);
        char addr[33];
        listenfd = accept(sockfd, (struct sockaddr *)&clie_addr, &len);
        printf("%dth client connected.ip:%s,port:%d\n", i++, 
                inet_ntop(AF_INET, &serv_addr.sin_addr.s_addr, addr, sizeof(addr)),
                ntohs(serv_addr.sin_port));
        printf("fd.:%d\n", listenfd);
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

        pthread_create(&pid, &attr, deal, (void *)listenfd);
        pthread_attr_destroy(&attr);
    }
    close(listenfd);
    close(sockfd);
    return 0;
}

client端:

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/ip.h>
#include <arpa/inet.h>

#define SERV_PORT 6666
int main()
{
    struct sockaddr_in  serv_addr, clie_addr;
    int sockfd, len;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    char buf[BUFSIZ];

    bzero(&serv_addr, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);
    inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr.s_addr);


    connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    while(1)
    {
        fgets(buf, sizeof(buf), stdin);
        write(sockfd, buf, strlen(buf));
        len = read(sockfd, buf, sizeof(buf));
        write(STDOUT_FILENO, buf, len);
    }
    close(sockfd);

    return 0;
}
【AUTOSAR-DEM】-2.4-APP SWC如何读取MIL灯状态以及配置MIL灯 该篇博文将告诉您: MIL(Malfunction Indicator Lamp/Light)灯的点灯和灭灯过程; DEM模块如何配置MIL灯; APP SWC如何获取MIL灯状态。 阅读详情

相关推荐

MPU6050的四元数解算姿态方法

使用MPU6050硬件DMP解算姿态是非常简单的,下面介绍由三轴陀螺仪和加速度计的值来使用四元数软件解算姿态的方法。 我们先来看看如何用欧拉角描述一次平面旋转(坐标变换): MPU6050的四元数解算姿态方法 设坐标系绕旋转α角后得到坐标系,在空间中有一个矢量在坐标系中的投影为,在内的投影为由于旋转绕进行,所以Z坐标未变,即有。 转换成矩阵形式表示为: 即 所以从旋转到可以写成上面仅仅是绕一根轴的旋转,如果三维空间中的欧拉角旋转要转三次: MPU6050的四元数解算姿态方法 上面得到了一个表示旋转的方

qq_41938005的博客 8392

TCP网络常见调优参数之一:SO_LINGER算法

具体现象是对于一个处理大量短连接的服务器,如果是由服务器主动关闭客户端的连接,将导致服务器端存在大量的处于TIME_WAIT状态的socket,甚至比处于Established状态下的socket多的多,严重影响服务器的处理能力,甚至耗尽可用的socket,停止服务。测试过程中也发现偶尔recv返回值为0的情况,这种情况应该是我们期望的结果,recv返回0的时候,说明接收到了http客户端主动close后发出的FIN报文,只有主动关闭的socket的一方才会有TIME_WAIT状态。

li_danwang的专栏 2145

Python-Opencv中的膨胀和腐蚀

Python-Opencv中的膨胀和腐蚀 腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分。 膨胀就是图像中的高亮部分进行膨胀,“邻域扩张”,效果图拥有比原图更大的高亮区域。腐蚀就是原图中高亮部分被腐蚀,“邻域被蚕食”,效果图拥有比原图更小的高亮区域。 1.膨胀 膨胀过程是有一个结构元素或者模板去在原图像素比对,当比对过程中,中心像素位置的值根据其八邻域取或运算,或运算为1就取自己的中心值,...

qq_44262417的博客 1万+

TCP协议中的SO_LINGER选项

SO_LINGER选项用来设置延迟关闭的时间,等待套接字发送缓冲区中的数据发送完成。没有设置该选项时,在调用close()后,在发送完FIN后会立即进行一些清理工作并返回。如果设置了SO_LINGER选项,并且等待时间为正值,则在清理之前会等待一段时间。 以调用close()主动关闭为例,在发送完FIN包后,会进入FIN_WAIT_1状态。如果没有延迟关闭(即设置SO_LINGER选项),在调用

Justlinux2010的专栏 2558

零代码构建AI智能体:COZE可视化工作流实战指南

AI智能体(AI Agent)是当前人工智能领域的重要发展方向,它通过模块化设计和工作流驱动,使大语言模型从被动对话转向主动执行。其核心原理在于将复杂的任务分解为可规划、可执行的步骤,并调用外部工具(插件)完成闭环。这一技术价值在于显著降低了自动化流程的开发门槛,让非程序员也能构建实用的数字助手。典型的应用场景包括智能客服、内容自动生成、数据分析和跨系统业务流程自动化。本文以COZE平台为例,深入解析如何通过其直观的可视化界面和丰富的插件生态,像搭积木一样快速搭建如“早安简报生成器”等实用智能体,并分享指令

468

预处理详解(三)—— 命令行定义 + 条件编译 + 文件包含

文章目录前言 前言

2021dragon的博客 2187

socket选项之SO_LINGER,优雅关闭套接字

本文章详细介绍如何优雅关闭套接字和套接字SO_LINGER选项如何使用,花5分钟时间可以轻松学懂。

weixin_28673511的博客 3214

浅谈Android MVI架构---大自然的搬运工~~~

浅谈 Android MVI架构

hong_world的博客 2155

tcp 选项:SO_LINGER祥解(转)

SO_LINGER    此选项指定函数close对面向连接的协议如何操作(如TCP)。缺省close操作是立即返回,如果有数据残留在套接口缓冲区中则系统将试着将这些数据发送给对方。   SO_LINGER选项用来改变此缺省设置。使用如下结构: struct linger {      int l_onoff;      int l_linger; };

miaoshaohoa的专栏 1150

用 ADBC 把动态查询做得又快又稳:从 CL_SQL_STATEMENT 到安全取数的工程化实践

本文介绍了ABAP中ADBC(ABAP Database Connectivity)技术的核心用法与最佳实践。ADBC作为Open SQL的补充,适用于动态查询、数据库特性调用等场景。文章通过示例代码详细演示了使用ADBC执行查询的完整流程:创建SQL语句、执行查询获取结果集、批量装载数据到内表,以及分包读取处理大数据量。特别强调了动态SQL的安全防护措施,包括输入转义和参数绑定等防注入技术。同时对比了ADBC与Open SQL的适用场景,指出ADBC更适合需要动态访问数据库原生功能的场合。文章还分析了代码

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1772

【Bug已解决】NCCL timeout for validation 解决方案

训练用多卡 DDP / FSDP 正常,但一到或者进程直接 hang 在 eval 的某个集合通信上。最迷惑的是:训练阶段(有集合通信)完全正常,偏偏 eval 阶段(看起来更轻量)超时。因为 eval 阶段某些 rank 没参与 collective,导致参与的那部分 rank 永远等不到同伴。

一键难忘的博客 142

一例TCP优雅关闭失败SO_LINGER选项未起作用

通过setsockopt :SO_LINGER 选项可以指定函数close对面向连接的协议如何操作。 内核缺省close操作是立即返回,如果有数据残留在套接口缓冲区中则系统将试着将这些数据发送给对方。 但是如果close时,接收缓冲区有未接收数据,则操作系统会直接发送RST报文结束链接,也就是说TCP链接不会优雅关闭。 所以,如果希望链接被优雅关闭,应在接受完缓冲区内的所有数据后再调用clo

镇关西拳打鲁智深 2201

130页5万字某市档案馆数字档案馆建设方案

【版权声明】本资料来源网络,仅用于行业知识分享,供个人学习参考,请勿商用。【侵删致歉】如有侵权请联系小编,将在收到信息后第一时间进行删除!完整资料领取见文末,部分资料内容:国家档案局证实颁布《数字档案馆建设指南》, 明确了数字档案馆建设原则、要求、目标,对相关系统建设内容、功能要求进行了概括和详细说明。数字档案馆系统建设应以 OAIS&nbsp;参考模型为设计基础,以实现数字资源的长期保存与可信管理。设计的数字档案馆系统架构如下图。图-1 数字档案馆体系结构数字档案馆建设包括五大层次和三大保障体系:

zuoan1993的博客 1180

25-tcp协议——连接复位(RST)

1. 连接复位(RST)   前面我们介绍了tcp连接建立和连接释放过程中的一些细节,那么大家有没有想过一些异常的情况:有时候也会出现无法建立tcp连接或tcp连接异常终止的情况。一般来说,导致这种情况的原因一般有很多种,比如:   1.拒绝连接请求,比如:A想和B建立tcp连接,但是A的连接请求中使用了一个不存在的端口(比如:这个端口超出65535的范围),那么B就可以发送RST报文段拒绝这...

网络安全 1万+

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

TCP复位报文段

一、访问不存在的端口 当客户端程序访问一个不存在的端口时,目标主机将给它发送一个复位报文段。 收到复位报文段的一端应该关闭连接或者重新连接,而不能回应这个复位报文段。 当客户端程序向服务器某个端口发起连接,而该端口仍被处于TIME_WAIT状态的连接所占用时,客户端也将收到复位报文段。 二、异常终止连接 对正常终止的连接:数据交换完成后,一方给另一方发送结束报文段,四次挥手断开连接。 TCP提供了...

Eric_qiushui的博客 598

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Java Socket 几个重要的TCP/IP选项解析(二)

1. SO_LINGER/ SO_REUSEADDR     TCP正常的关闭过程如下(四次握手过程): (FIN_WAIT_1) A       ---FIN--->       B(CLOSE_WAIT) (FIN_WAIT_2) A         (TIME_WAIT)A          (TIME_WAIT)A        ---ACK->       B(CLOSED

光线技术博客 354

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

TCP的状态变迁及RST报文段产生与处理

TCP状态变迁 CLOSE:                socket的初始状态,没有进行任何操作(connect, listen)之前的状态 LISTEN:               可以接受SYN的状态,服务器等待连接 SYN_RECEIVED:    一个连接请求已经到达,等待确认 SYN_SENT:            发出连接请求,等待确认 ESTABLISED:

2614

TCP链接异常关闭的情况

终止一个连接的正常方式是发送FIN。 在发送缓冲区中 所有排队数据都已发送之后才发送FIN,正常情况下没有任何数据丢失。 但我们有时也有可能发送一个RST报文段而不是F IN来中途关闭一个连接。这称为异常关闭 。  进程关闭socket的默认方式是正常关闭,如果需要异常关闭,利用 SO_LINGER选项来控制。 异常关闭一个连接对应用程序来说有两个优点: (1)丢弃任何待发

追求卓越 2588

linux 网络编程各种坑

TCP/IP协议相关 1、延时ack 当协议栈接受到TCP数据时,并不一定会立刻发送ACK响应,而是倾向于等待一个超时或者满足特殊条件时再发送。对于Linux实现,这些特殊条件如下: 1)收到的数据已经超过了 full frame size 2)或者处于快速回复模式 3)或者出现了乱序的包 4)或者接收窗口的数据足够多 如果接收方有数据回写,则ACK也会搭车一起发送。当以上条件都...

耿小渣的进阶之路 1130

SO_LINGER选项

SO_LINGER选项用于控制close系统调用在关闭TCP连接时的行为。默认情况下,当我们使用close系统调用来关闭一个socket时,close将立即返回,TCP模块负责把该socket对应的TCP发送缓冲区中残留的数据发送给对方。设置(获取)SO_LINGER选项的值时,我们需要给setsockopt(getsockopt)系统调用传递一个linger类型的结构体,其定义如下:#includ

tengyft的专栏 3655

《Linux高性能服务器编程》学习笔记——第五章 Linux网络编程基础API(4)

socket选项 fcntl系统调用是控制文件描述符属性的通用POSIX方法。下面两个是专门读取和设置socket文件描述符属性的方法: #include int getsockopt(int sockfd, int level, int option_name, void* option_value, socklen_t* restrict option_len); int se

爱很遥远 579

Linux服务器编程实践52-SO_LINGER选项:控制close关闭TCP连接的行为

本文详细介绍了Linux中SO_LINGER选项对TCP连接关闭行为的控制机制。通过设置linger结构体的l_onoff和l_linger参数,可以实现三种关闭策略:默认异步关闭(l_onoff=0)、强制立即关闭(l_onoff=1,l_linger=0)和延迟关闭(l_onoff=1,l_linger>0)。文章通过代码示例演示了不同配置下的实际效果,并分析了适用场景和注意事项。建议根据业务需求合理选择策略:默认策略保证可靠性,强制策略适用于异常恢复,延迟策略平衡安全与效率。使用时应避免滥用强制

文石_2009的博客 1032

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

1.TCP的异常关闭 正常终止一个连接的方法是发送一个FIN报文。有时也称为有序释放,因为所有排队数据都发送完之后才发送FIN,正常情况下没有任何数据的丢失。但也可能发送一个复位报文段而不是FIN来释放一个连接。有时称这位异常释放(abortive release)。 异常终止一个连接对应用程序来说有两个优点: 丢弃任何待发送数据并立即发送复位报文段 RST的接收方会区分另一端执行的是异常...

paradox_1_0的博客 851

TCP异常处理(accept返回前连接中止)与SO_LINGER选项

一、accept返回前终止分析 问题一: 因为accept是堵塞的, 并且等待来自客户端的连接, 但是, 如果在accept期间 , 如果因为系统调用中断了accept就会返回一个非致命的错误, 而此时有来自客户端进行TCP三路握手完成后, 而我们通过循环在此调用accept函数可以完成连接,。因为TCP的连接是在内核中完成的, 与accept函数的执行无关。 问题二: 如果我们在调用ac

xiaomiCJH的博客 3634

SO_LINGER作用

SO_LINGER这个选项在我以前带队改造haproxy的时候引出过一个reset(RST)客户端连接的bug。SO_LINGER作用设置函数close()关闭TCP连接时的行为。缺省close()的行为是,如果有数据残留在socket发送缓冲区中则系统将继续发送这些数据给对方,等待被确认,然后返回。利用此选项,可以将此缺省行为设置为以下两种  a.立即关闭该连接,通过发送RST分组(而不是用正常...

coolboywjun的专栏 1万+

SO_LINGER选项的作用

SO_LINGER选项用于设置函数close()关闭TCP连接时的行为。 缺省close()的行为是,如果有数据残留在socket发送缓冲区中则系统将继续发送这些数据给对方,等待被确认,然后返回。 利用此选项,可以将此缺省行为设置为以下两种: a.立即关闭该连接,通过发送RST分组(而不是用正常的FIN|ACK|FIN|ACK四个分组)来关闭该连接。至于发送缓冲区中如果有未发送完的数据,则丢弃。主动关闭一方的TCP状态则跳过TIMEWAIT,直接进入CLOSED。网上很多人想利用这一点来解决服务器上出现大

judith的博客 644
上一篇: linux0.11源码研究---exit.c
下一篇: 文件描述符、文件表项、v节点表项的联系
UKey_
博客等级 码龄10年 258粉丝 186原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值