HTTP长连接实现原理

1. HTTP长连接和短连接的定义

  • HTTP长连接
    • 浏览器向服务器进行一次HTTP会话访问后,并不会直接关闭这个连接,而是会默认保持一段时间,那么下一次浏览器继续访问的时候就会再次利用到这个连接。
    • 在HTTP/1.1版本中,默认的连接都是长连接,我们可以通过Connection: keep-alive字段进行指定。
  • HTTP短连接
    • 浏览器向服务器每进行一次HTTP操作都要建立一个新的连接。
    • 在HTTP/1.0版本中默认是短链接

2.  HTTP长连接本质

HTTP协议本质是OSI七层参考模型中的应用层协议,而网络进行通信的时候都是通过上层协议封装头部后作为下层协议的数据部分进行封装的,而实际中我们经常接触的是TCP/IP协议簇,也就是传输层利用TCP协议和网络层利用IP协议。因此HTTP协议的长连接本质上就是TCP的长连接。

2.1 TCP建立连接回顾

上面我们提到了TCP,那么回顾一下,通信双方在进行通信的时候就是要通过“三次握手“来建立连接的,握手的过程大致如图1所示:

8a617202309281028326356.png

那么通过上图我们就可以清楚的看到,服务器和客户端都建立了一个TCB传输控制块,这里就是我们进行socket编程的时候管理连接的地方,在这里我们先标记这个TCB,在后续的文章,我们会详细介绍在Linux中TCB是怎么样管理连接的。

2.2  TCP释放连接回顾

在回顾了TCP连接建立之后,我们不妨再来看看TCP四次挥手,如图2所示:

9b86f20230928102908677.png

TCP连接的释放是看通信双方谁是主动关闭的一方,谁是被动关闭的一方来决定各自状态的,具体的内容大家依然可以参考《TCP/IP详解》,这里就不再赘述了。

2.3 TCP长连接

在建立了TCP连接之后,这也就到了这篇文章中比较核心的问题,就是说TCP连接建立之后,并不会在完成一次数据通信后就关闭连接,而是要保持一段时间,那么这个时间是怎么样保证,又是谁保证的呢?

2.3.1 TCP保活机制
  • 为什么要有保活机制?
    • 第一点自然是我们这篇文章的主题,通过保活机制,我们可以保证通讯双方的连接不被释放掉
    • 第二点就是在另一些情况下,如果客户端或者服务器发生了错误或者宕机,那么就可以依靠这种保活机制探测出网络通信出现了问题,进而可以释放掉这种错误连接。
  • 保活机制

首先保活机制的工作原理就是,通过在服务器端设置一个保活定时器,当定时器开始工作后就定时的向网络通信的另一端发出保活探测的TCP报文,如果接收到了ACK报文,那么就证明对方存活,可以继续保有连接;否则就证明网络存在故障。

上面只是在原理层面简单的介绍,根据文献[1],我们可以了解到详细的内容:

如果一个给定的连接在两个小时之内没有任何动作,则服务器就向客户发送一个探查报文段。客户主机必须处于以下 4个状态之一。

状态1:客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方是正常工作的。服务器在两小时以后将保活定时器复位。如果在两个小时定时器到时间之前有应用程序的通信量通过此连接,则定时器在交换数据后的未来2小时再复位。

状态2:客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应。服务器将不能够收到对探查的响应,并在75秒后超时。服务器总共发送10个这样的探查,每个间隔75秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接。

状态3:客户主机崩溃并已经重新启动。这时服务器将收到一个对其保活探查的响应,但是这个响应是一个复位,使得服务器终止这个连接。

状态4:客户主机正常运行,但是从服务器不可达。这与状态2相同,因为TCP不能够区分状态4与状态2之间的区别,它所能发现的就是没有收到探查的响应。

  • 实际应用

那么我们在了解了理论上TCP长连接是通过保活机制来实现的,但是保活机制并不是RFC规定的TCP协议的内容,因此有时候在不支持保活机制的机器上,往往我们也需要先看一下内核层面是否支持,如果不支持需要在应用层自己去实现这个功能。

在这里我们就来看一下Linux相关的TCP保活参数

tcp_keepalive_time,单位:秒,表示发送的探测报文之前的连接空闲时间,默认是7200s。

tcp_keepalive_intvl,单位:秒,表示两次探测报文之间的间隔时间,默认是75s

tcp_keepalive_probes,单位,秒,表示探测的次数,默认是9

接下来如果我们需要在应用层写自己的心跳机制,那么就需要其他方面的一些内容了。

2.3.2 TCP长连接和短链接比较
  • TCP短链接
    • 优点
      • 短链接不占服务器的内存,服务器能处理的连接数量会比较多
    • 缺点
      • 在有实际的资源要进行数据通信的时候才建立连接,那么在客户端发送完数据释放连接之后当服务器有向客户端发送数据时就不能做到发送消息的实时性。
      • 频繁地建立连接、释放连接会耗费大量的CPU和网络带宽资源。
  • TCP长连接[2]
    • 优点
      • 通信双方因为在保活机制的保证下可以保证数据收发的实时性
    • 缺点
      • 因为服务器需要一直保存和客户端的这条链接,因为是有状态的,那么在大量并发连接请求过来时,系统资源可能就不够了。
    • 什么时候需要长连接
      • 服务器需要主动发送资源给客户端时
      • 客户端和服务器通信很频繁时
      • 客户端宕机或者掉线时需要服务器做一些处理时
    • TCP长连接设计时需要考虑的问题
      • 默认的keep-alive时间比较长,一般的业务可能不需要这么久的时间
      • socket proxy会让TCP的保活失效:多有的proxy应用只能转发TCP的应用数据,不能转发TCP协议内部的包

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

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

相关文章

JVM面试题:(二)内存结构和内存溢出、方法区的两种实现

内存结构: 方法区和对是所有线程共享的内存区域;而java栈、本地方法栈和程序员计数器是运行是线程私有 的内存区域。 Java堆(Heap),是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内 存区域,在…

VuePress实现自动获取文章侧边栏目录功能

👨🏻‍💻 热爱摄影的程序员 👨🏻‍🎨 喜欢编码的设计师 🧕🏻 擅长设计的剪辑师 🧑🏻‍🏫 一位高冷无情的编码爱好者 大家好,我是 DevO…

MFC 鼠标悬停提示框

MFC 鼠标悬停提示框 运行效果 在MFC窗口中添加一个控件 工具栏中拖拽List Box到MFC窗口给List Box添加变量 CListBox m_listbox 增加成员变量 CWnd* m_tip_parent_wnd; CToolTipCtrl m_tip;给m_listbox创建提示框 void create_tip_window(CWnd* tip_wnd, CToolTipCtrl* ti…

从 0 到 1 ,手把手教你编写《消息队列》项目(Java实现) —— 创建虚拟机

文章目录 一、虚拟机二、关于消息的API发布消息直接交换机 DIRECT 转发规则扇出交换机 FANOUT 转发规则主题交换机 TOPIC 转发规则匹配规则Router类 订阅消息消费者队列如何给订阅的消费者发送消息自动发送消息至订阅者 应答消息 三、代码编写 一、虚拟机 接下来要创建虚拟机,…

el-date-picker增加默认值 修改样式

预期效果 默认是这样的 但希望是直接有一个默认的当天日期,并且字体颜色啥的样式也要修改(在这里假设今天是2023/10/6 功能实现 踩了坑挺多坑的,特此记录 官方文档 按照官方的说明,给v-model绑定一个字符串就可以了 在j…

AI能否取代程序员:探讨人工智能在编程领域的角色

引言: 随着人工智能(AI)技术的快速发展,人们开始思考:AI是否能够取代程序员?这个问题引发了广泛的讨论和辩论。一些人认为,AI的出现将彻底改变编程的面貌,而另一些人则坚信&#xf…

大数据之LibrA数据库系统介绍

简介 LibrA是一个基于开源数据库Postgres-XC开发的分布式并行关系型数据库系统。 LibrA提供了以下功能: 标准SQL支持 支持标准的SQL92/SQL2003规范,支持GBK和UTF-8字符集,支持SQL标准函数与OLAP分析函数,支持存储过程。 数据库…

微信支付v2

文档: https://pay.weixin.qq.com/wiki/doc/api/index.html 微信小程序:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter11_1 需要一个微信认证后的小程序,,还需要一个,在微信商户平台,&…

串级/级联控制知识点整理

串级控制系统是改善控制质量的有效方法之一,在过程控制中得到了广泛的应用。所谓串级控制,就是采用两个控制器串联工作,外环控制器的输出作为内环控制器的设定值,由内环控制器的输出去操纵控制阀,从而对外环被控量具有…

mysql8压缩包安装

MySQL 8.0 版压缩包安装教程_mysql 压缩包 8.0安装-CSDN博客 1、mysql压缩包 2、参考链接一步一步操作即可。 3、安装,破解navicat. 4、无法连接,参考该链接修改: Mysql 解决1251- Client does not support authentication protocol reques…

android app开发环境搭建

Android是流行的移动设备原生应用开发平台,其支持Java语言以及Kotlin语言的开发环境,本文主要描述官方提供的Android studio集成开发环境搭建。 https://developer.android.google.cn/ 如上所示,从官方上下载最新版本的Android studio集成开…

【DevOps】搭建你的第一个 Docker 应用栈

搭建你的第一个 Docker 应用栈 1.Docker 集群部署2.第一个 Hello World2.1 获取应用栈各节点所需镜像2.2 应用栈容器节点互联2.3 应用栈容器节点启动2.4 应用栈容器节点的配置2.4.1 Redis Master 主数据库容器节点的配置2.4.2 Redis Slave 从数据库容器节点的配置2.4.3 Redis 数…

[NISACTF 2022]join-us - 报错注入无列名注入

[NISACTF 2022]join-us 解题流程 解题流程 点击登录,找到注入点 这种框,可以直接爆破关键字,看是否拦截,也可以手动尝试,发现、union、and、or、substr、database等关键字都拦截了 1、学到了:可以用数据库…

pytorch学习------TensorBoard的使用

目录 简介使用方式1、单条曲线(scalar)2、多条曲线(scalars)3、直方图(histogram)4、图片(image)5、渲染(figure)6、网络(graph) 简介 建好一个神经网络,其实我们也不知道神经网络里头具体细节到底做了什么,要人工调试十分困难(就好比你无法想象出递归的…

SpringCloud之Stream框架集成RocketMQ消息中间件

Spring Cloud Stream 是一个用来为微服务应用构建消息驱动能力的框架。它可以基于 Spring Boot 来创建独立的、可用于生产的 Spring 应用程序。Spring Cloud Stream 为一些供应商的消息中间件产品提供了个性化的自动化配置实现,并引入了发布-订阅、消费组、分区这三…

SQL Server 简介与 Docker Compose 部署

今天我翻阅了在之前公司工作时的笔记,发现了有关数据库的一些记录。当时,我们的项目开始使用 Oracle 数据库,但后来由于一些项目需求的变更,我们切换到了 SQL Server 。值得一提的是,公司当时也开始采用 Docker 技术&a…

c++模板库容器list vector map set操作和性能对比

文章目录 listvectormapset性能比较总结 list 列表&#xff08;list&#xff09;是C STL中的一种容器类型&#xff0c;它是一个双向链表&#xff0c;可以在任意位置高效地添加、删除、移动元素。 以下是一些常用的列表操作&#xff1a; 创建列表 #include <list> std…

Jetson Orin NX 开发指南(1): 系统烧录

一、SDK Manager SDK Manager 工具是 NVIDIA 官方推荐的烧写和管理 Jetpack 系统组件的一个图形化烧写工具&#xff0c;使用起来非常的简单方便&#xff0c;但是该软件需要在 x86 的 Ubuntu 18.04 或 Ubuntu 20.04 的系统上运行&#xff0c;因此我们需要准备一台安装了 Ubuntu…

记录:Unity脚本的编写3.0

目录 前言前置控制方法查看效果移动方式 前言 前面记录了一些通过脚本控制对象模型移动和通过用户的操作对模型进行变化的方法&#xff0c;那么为了让我们创造的不论是地形还是模型都拥有真实的物理引擎&#xff08;大雾&#xff09;&#xff0c;那么这次就使用脚本控制模型感…

函数reshape(-1,)里的-1的意思

reshape函数是对narray的数据结构进行维度变换&#xff0c;由于变换遵循对象元素个数不变&#xff0c;在进行变换时&#xff0c;假设一个数据对象narray的总元素个数为N&#xff0c;如果我们给出一个维度为&#xff08;m&#xff0c;-1&#xff09;时&#xff0c;我们就理解为将…