TCP协议的长连接和短连接详解

news2024/11/14 15:17:48

一 前言

TCP在真正开始进行数据传输之前,Server 和 Client 之间必须建立一个连接。当数据传输完成后,双方不再需要这个连接时,就可以释放这个连接。

TCP连接的建立是通过三次握手,而连接的释放是通过四次挥手。所以说,每个TCP连接的建立和释放都是需要消耗资源和时间成本的。

二 TCP短连接

模拟一种TCP短连接的情况:

client 向 server 发起连接请求

server 收到连接请求,双方建立TCP连接

client 向 server 发送消息

server 回应 client 消息

一次读写完成,此时双方任何一方都可以发起关闭连接请求,即close操作。

在步骤5中,一般都是 client 先发起close操作。从上面的描述来看,短连接一般只会在 client 和 server 之间传递一次读写操作。

短连接的操作过程:建立连接 ——> 传输数据 ——> 关闭连接。

三 TCP长连接

模拟一种长连接的情况:

client 向 server 发起连接请求

server 收到连接请求,双方建立TCP连接

client 向 server 发送消息

server 回应 client 消息

一次读写完成,TCP连接不关闭

后续读写操作...

长时间操作之后,client 发起关闭连接请求

TCP长连接是指在连接成功建立之后,即使通信双方没有数据传输也要保持连接,使其不断开。

长连接的操作步骤:建立连接 ——> 传输数据 ——> ... (保持连接) ... ——> 传输数据 ——> 关闭连接

四 长连接和短连接的优缺点

4.1 短连接的优缺点

优点:管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段。

缺点:由于TCP的建立和关闭操作需要一定的系统开销,如果客户端连接请求频繁,会降低服务器的处理速度、浪费系统资源和带宽。

4.2 长连接的优缺点

优点:长连接可以省去较多的TCP连接的建立和关闭的操作,减少浪费,节约时间。

缺点:client 与 server 之间的连接如果一直不关闭的话,会存在一个问题,随着客户端的连接越来越多,服务器的负载压力会增大,降低服务器的整体性能,更严重者,可能导致服务器崩溃;其次,如果大量处于连接状态的TCP通信双方长时间没有进行数据传输,这也会浪费系统和网络资源。

相关视频推荐

Tcp/ip协议栈技术专题训练营(1)

Tcp/ip协议栈技术专题训练营(2)

100行代码实现tcp/ip协议栈,自行准备好Linux系统

五 长连接/短连接的应用场景

长连接一般多用于需要频繁进行读写操作,点对点通讯,而且连接数不太多的情况。

例如:数据库的连接通常使用长连接,如果用短连接的话,频繁的TCP socket创建和关闭,会造成socket错误,也是对资源的一种浪费。

短连接一般用于不需要频繁进行读写操作,并且连接数很大的情况下。

例如:web网站的http服务一般都用短连接。因为长连接对于服务器来说是要耗费一定的系统资源的,像web网站服务,通常会有大量的客户端连接请求,并发连接量大,使用短连接会更节省系统资源,能够及时响应客户请求。

总结:长连接和短连接的选择要具体需求、实际情况而定。

六 长连接的保活机制

对于TCP长连接,当通信双方在没有数据传输的时候,如何保持TCP连接一直处于“保活(KeepAlive)”状态,这是一个必须要解决的问题。

在Linux系统中,我们可以使用 netstat、lsof等命令可以查看TCP连接是否处于“ESTABLISHED”状态。

6.1 TCP保活的必要性

(1)很多防火墙会主动关闭空闲的socket。

(2)可能出现的非正常断连,服务器并不能检测到,为了回收已断连的socket资源,必须提供一种检测机制。

导致TCP非正常断连的可能原因:
(1)网络故障
(2)客户端/服务端一侧突然断电或者进程崩溃

6.2 保活机制的方式

6.2.1 应用层的心跳机制

在应用层中使用心跳(heartbeat)机制来主动检测。具体做法:当TCP连接建立成功后,客户端开启一个定时任务,定时对已经建立连接的对端发送一个心跳请求消息,服务器收到该心跳消息后,返回一个心跳应答消息。如果在超时时间内没有收到服务器的应答消息,则重发心跳请求消息,如果客户端持续多次没有响应,客户端则可以认为该TCP连接不可用,主动断开连接。当然,也可以是服务器端主动发送心跳请求消息给客户端。

6.2.2 TCP协议自带的保活机制

Linux内核自带的保活机制keep-alive。使用的时候只需要打开keep-alive功能即可。

TCP的Keepalive机制的作用是在于探测连接的对端是否存活。

工作原理:TCP keep-alive是通过在空闲时发送TCP Keep-Alive数据包,然后对方回应TCP Keep-Alive ACK来实现的。

在socket网络编程中,需要设置一个socket选项 SO_KEEPALIVE,才能开启keepalive机制。代码描述如下:

keepAlive = 1;
 
setsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(keepAlive));

在Linux的keepalive机制中,有3个重要的内核参数:tcp_keepalive_time、tcp_keepalive_probes 和 tcp_keepalive_intvl。

tcp_keepalive_time:表示TCP连接闲置多长时间后开始发送探测报文。(单位:秒)

tcp_keepalive_probes:表示一次探测过程中最多可以重发探测报文的次数。(没有收到确认时重发次数)

tcp_keepalive_intvl:表示前一个探测报文和后一个探测报文之间的时间间隔。(即超时重传的时间间隔)(单位:秒)

这些内核参数可以在/proc/sys/net/ipv4/目录下可以看到,也可以使用Linux命令查看其默认值:

# sysctl -a |grep keepalivenet.ipv4.tcp_keepalive_intvl = 75net.ipv4.tcp_keepalive_probes = 9net.ipv4.tcp_keepalive_time = 7200

可以看到,这3个内核参数的默认值分别为:

tcp_keepalive_time = 7200秒,即2小时。也就是说,从最后一次数据传输结束开始计时起到发送第一个保活探测报文的时间间隔为2小时。

tcp_keepalive_probes = 9。当没有收到对方的确认时,继续发送保活探测报文的默认次数为9次。

tcp_keepalive_intvl = 75秒。当没有收到对方的确认时,继续发送保活探测报文的间隔时间为75秒。

TCP连接探活的过程

开启 keepalive后,如果2小时内在此TCP连接的通信双方没有发生数据交换,TCPT就自动给对方发一个保活探测报文段(keepalive probe)。这是一个对方必须响应的TCP报文段。

它会导致以下三种情况:

对方成功接收,连接正常:以期望的ACK报文段响应。2小时后,TCP将发出另一个探测报文。

对方已崩溃且已重新启动:已RST报文段响应。socket的待处理错误被置为ECONNRESET,socket本身则被关闭,断开TCP连接。

对方无任何响应:发送保活探测报文的一方,相隔75秒后,再次重发保活探测报文,重发8次,一共尝试9次。若仍无响应就放弃。socket的待处理错误被置为ETIMEOUT,socket本身则被关闭,断开TCP连接。

设置TCP keepalive

上面提到的 TCP keepalive使用的是其默认值。如果我们不想使用这么长的等待时间,可以修改Linux内核关于网络方面的配置参数。我们可以自定义那3个内核参数的值,有两种修改方式:

(1)全局设置(操作系统层面)

(2)针对单个TCP连接设置(应用程序层面)

1、全局设置

在Linux系统中,我们可以通过修改 /etc/sysctl.conf 配置文件的全局配置:

net.ipv4.tcp_keepalive_time=300net.ipv4.tcp_keepalive_intvl=30net.ipv4.tcp_keepalive_probes=5

添加上面的配置后,输入:sysctl -p 使其生效。

这种方法设置的全局内核参数,针对整个操作系统生效,对单个socket的设置不够友好。

2、针对单个TCP连接的设置

我们可以在socket网络编程中设置TCP的 TCP_KEEPCNT、TCP_KEEPIDLE、TCP_KEEPINTVL 这3个socket选项。

这三个选项的定义,可以通过man 命令查看。

man 7 tcp

TCP_KEEPCNT (since Linux 2.4)
The maximum number of keepalive probes TCP should send before dropping the connection. This option should not be
used in code intended to be portable.
关闭一个非活跃连接之前的最大重试次数。 该选项不具备可移植性。
TCP_KEEPIDLE (since Linux 2.4)
The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes, if the
socket option SO_KEEPALIVE has been set on this socket. This option should not be used in code intended to be
portable.
设置连接上如果没有数据发送的话,多久后发送keepalive探测报文,单位是秒。该选项不具备可移植性。
TCP_KEEPINTVL (since Linux 2.4)
The time (in seconds) between individual keepalive probes. This option should not be used in code intended to be
portable.
前后两次探测报文之间的时间间隔,单位是秒。该选项不具备可移植性。

代码层面的设置步骤如下:

int keepAlive = 1;    // 非0值,开启keepalive属性int keepIdle = 60;    // 如该连接在60秒内没有任何数据往来,则进行此TCP层的探测int keepInterval = 5; // 探测发包间隔为5秒int keepCount = 3;    // 尝试探测的最多次数//开启tcp-keepAlive探活机制
setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(keepAlive));
 
setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, &keepIdle, sizeof(keepIdle));
 
setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, &keepInterval, sizeof(keepInterval));
 
setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, &keepCount, sizeof(keepCount);

6.2.3 TCP Keepalive 常见异常

启用TCP Keepalive 的应用程序,一般可以捕获到下面几种类型的错误:

ETIMEOUT 超时错误

在发送一个探测报文段后经过(tcpkeepaliveTime + tcpkeepaliveIntvl * tcpkeepaliveProbes)时间后仍然没有接收到ACK确认报文段的情况下触发的异常,套接字被关闭:Connection timedout。

EHOSTUNREACH 主机不可达错误

这个是网络层的ICMP汇报给上层应用的异常错误:No route to host。

6.2.4 TCP Keepalive 和 应用层 heartbeat 优缺点

1、TCP协议的 Keepalive 机制

优点:TCP协议的Keepalive机制由系统内核实现,上层应用程序只需要处理数据的收发,连接异常通知即可,这就减少了应用层代码的复杂度,内核层面的计时器相比应用层,更为高效。

缺点:第一,TCP keepalive机制,位于传输层,由操作系统负责,只能检测到连接是否存活,但不能检测检测连接是否可用。例如,服务器因为某种原因导致负载超高,CPU使用率达到了100%,无法继续响应任何业务请求,但是TCP探针却仍能确定连接状态,这就是典型的连接活着但是服务已死的状态。对于客户端而言,这时最好的选择就是断开连接重新连接到其他服务器上,而不是一直认为当前服务器仍处于可用状态,一直向当前服务器发送那些必然会失败的请求。

第二,TCP keepalive机制 对于连接异常断开的情况不能及时有效地监测到。如果TCP连接的某一方突然异常断开连接,这个时候发送方并不知道对端已经掉线。而此时,如果有数据发送失败,tcp会自动进行超时重传,而重传报文段的优先级是要高于keepalive的探测报文段的,导致探测报文段总是不能发送出去,直到经过较长时间的重传之后,我们才会知道。

2、应用层的HeartBeat 机制

优点:第一,具有更好的灵活可控性。可以控制心跳的监测时机、间隔和流程,甚至可以在心跳包上附带额外信息,最重要的是不光可以检测连接是否存在,还可以检测到连接是否可用,而TCP的keepalive机制只能提供简单的检活功能。

第二,具有通用性。应用层的心跳不依赖传输层协议,如果有一天不用TCP要改用UDP了,传输层不提供心跳机制了,但是你应用层的心跳机制依然可以使用,只需做少许改动就可以继续使用。

缺点:第一,需要开发人员自己实现,增加软件开发的工作量,由于应用特定的网络框架,还可能增加代码结构的复杂度。

第二,应用层心跳的流量消耗会更大,毕竟这本质上还是一个普通的数据包。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/172203.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【SpringCloud】Eureka的基本原理与使用

【SpringCloud】Eureka的基本原理与使用 一、Eureka-提供者与消费者 【问】如果服务A调用了服务B,而服务B又调用了服务C,服务B的角色是什么? 二、Eureka的结构和作用 什么是Eureka? Eureka 解决服务调用的问题 order-servic…

博物馆3d数字化全景展示设计方案

作为近几年新兴的营销方式,交互式营销能够让消费者对产品从主动感兴趣到互动体验,甚至自主自发传播,达到“在销售中传播,在传播中销售”的目的。进入数字体验经济时代,当3d数字化展示技术遇上传统行业,3d数…

Redis原理篇(三)通信协议

一、RESP协议 1、定义 Redis是一个cs架构的软件,通信一般分两步: 客户端client向服务端server发送一条命令服务端解析并执行命令,返回响应结果给客户端 因此客户端发送命令的格式、服务端响应结果的格式必须有一个规范,这个规…

HashMap源码学习:JDK1.8版本源码解析

文章导航 HashMap源码学习:红黑树原理详解 HashMap源码学习:JDK1.8版本源码解析 目录文章导航前言正文HashMap重要属性HashMap构造方法HashMap扩容方法HashMap链表迁移HashMap红黑树迁移HashMap链表转红黑树HashMap红黑树转链表HashMap添加数据HashMap移…

让你彻底明白Java SPI与SpringBoot自动配置,内附实例代码演示

一、Java SPI的概念和术语 SPI:全称是Service Provider Interface:是一种基于ClassLoader来发现并加载服务的机制 SPI由三个组件构成:Service、Service Provider、ServiceLoader Service:是一个公开的接口或抽象类,定…

数说菊风2022

春风传捷报, 梅韵贺新年! 2022,已悄然划过, 就让我们用数字说话, 述说这年的精彩! 树十大标杆案例 国际运营商战略合作——Telkomsel 携手印尼运营商Telkomsel在RCS融合通信和RTC实时音视频领域形成合…

golang入门笔记——kitex

WSL的安装 由于Kitex并不支持Linux,所以需要首先安装WSL2 WSL一句话来说就是微软出的一个虚拟机工具 Win11下安装WSL2的步骤为: 1.“开始菜单”搜索功能,打开“启动或关闭Window功能” 2.勾选以下功能 1.适用于Linux的Window子系统 2.虚…

qsort函数

目录1.什么是qsort函数2.实现一个qsort函数3.用qsort函数排序一个结构体4.模仿qsort的功能实现一个通用的冒泡排序1.什么是qsort函数 我们以前学习过的一些排序算法,如冒泡、希尔、快排等等,它们速度有快有满,但是这些排序都只能排序一种类型…

iOS 内存泄漏检测 Instruments Leaks

Xcode 中 按住 command I 或者菜单栏 Product – Profile 2. 双击 Leaks 或者按 choose,打开 Leaks 面板 3. 在显示的 Leaks 面板中,点击左上角红色点,即可运行内存检测。 4. 在运行过程中如果发现Leak Checks(如图)…

【C进阶】C进阶练习编程题

⭐博客主页:️CS semi主页 ⭐欢迎关注:点赞收藏留言 ⭐系列专栏:C语言进阶 ⭐代码仓库:C Advanced 家人们更新不易,你们的点赞和关注对我而言十分重要,友友们麻烦多多点赞+关注,你们…

关闭“此版本的Windows不再支持Microsoft Edge”提示

在Win7中,安装Microsoft Edge,升级到“109.0.1518.55 (正式版本)”后,打开Edge会弹出提示: 此版本的 Windows 不再支持 Microsoft Edge。升级到 Windows 10 或更高版本,以从 Microsoft Edge 获取常规功能和安全更新。 …

ESPNet: 自动驾驶领域轻量级分割模型

论文标题:ESPNet: Efficient Spatial Pyramid of Dilated Convolutions for Semantic Segmentation 论文地址:https://arxiv.org/pdf/1803.06815v2.pdf 开源地址: https://github.com/sacmehta/ESPNet 论文思想 ESPNet是用于语义分割的轻量…

一文弄懂Linux虚拟机网络配置

文章目录计算机网路基础网络连接模式Bridged(桥接模式)NAT(地址转换模式)Host-Only(仅主机模式)Linux常用网络相关命令ifconfig:配置网络接口ping:测试主机之间网络连通性修改ip地址…

Threejs 导入动态模型 - 兔子岛

Threejs 动画模型GLTF加载器(GLTFLoader) glTF(gl传输格式)是一种开放格式的规范 (open format specification), 用于更高效地传输、加载3D内容。该类文件以JSON(.gltf)…

产品心理学:福格行为模型详解与应用

​Fogg说人的行为由动机,能力和触发条件这三要素组成,这三个同时都满足时行为才会发生。用一个等式来简化就是: BMAT 其中B是Behavior行为,M是Motivation 动机,A是Ability能力,T是Triggers触发。 行为的发…

“华为杯”研究生数学建模竞赛2004年-【华为杯】B题:实用下料的数学模型(附优秀论文)

赛题描述 “下料问题(cutting stock problem)”是把相同形状的一些原材料分割加工成若干个不同规格大小的零件的问题,此类问题在工程技术和工业生产中有着重要和广泛的应用. 这里的“实用下料问题”则是在某企业的实际条件限制下的单一材料的下料问题。 一个好的下料方案首先…

JavaEE4-Spring使用

目录 1.存储Bean对象到Spring容器中 1.1.创建Bean 1.2.将Bean注册到Spring容器中 1.2.1.第一次存储Bean(可选,如果是第二次及以后,此步骤忽略) 1.2.2.添加Bean标签 2.从Spring容器中获取并使用Bean对象 2.1.创建Spring上下…

ADC架构_Flash

ADC架构_Flash 比较器做1位ADC Vin > Vref Vout High&#xff08;1&#xff09; Vin < Vref Vout Low&#xff08;0&#xff09; 比较器是组建集成ADC的内部基本而又关键的模块&#xff1b;在比较器应用在ADC中一般要求很高的分辨率&#xff0c;也就是很小的差分输…

Spring Security 认证研究

2 Spring Security 认证研究 2.1 Spring Security介绍 认证功能几乎是每个项目都要具备的功能&#xff0c;并且它与业务无关&#xff0c;市面上有很多认证框架&#xff0c;如&#xff1a;Apache Shiro、CAS、Spring Security等。由于本项目基于Spring Cloud技术构建&#xff…

java数组2023014

数组&#xff1a;首先数组也是一种类型 Java的数组要求所有的数组元素具有相同的数据类型。因此&#xff0c;在 一个数组中&#xff0c;数组元素的类型是唯一的&#xff0c;即一个数组里只能存储一种数据类型的数据&#xff0c;不能存储多种数据类型的数据。 注意&#xff1a; …