HTTP协议中的短轮询、长轮询、长连接和短连接 序言 最近刚到公司不到一个月,正处于熟悉项目和源码的阶段,因此最近经常会看一些源码。在研究一个项目的时候,源码里面用到了HTTP的长轮询。由于之前没太

本文主要是介绍HTTP协议中的短轮询、长轮询、长连接和短连接 序言 最近刚到公司不到一个月,正处于熟悉项目和源码的阶段,因此最近经常会看一些源码。在研究一个项目的时候,源码里面用到了HTTP的长轮询。由于之前没太,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

HTTP协议中的短轮询、长轮询、长连接和短连接

序言

最近刚到公司不到一个月,正处于熟悉项目和源码的阶段,因此最近经常会看一些源码。在研究一个项目的时候,源码里面用到了HTTP的长轮询。由于之前没太接触过,因此LZ便趁着这个机会,好好了解了一下HTTP的长长短短。

了解的方式主要都是LZ在网络上获取的,这里只是谈一下LZ对于这四种叫法最直观的理解。如果你之前不懂的话,可以帮你普及一下,如果你之前就懂得话,可以互相对照一下。

以前的误解

很久之前LZ就听说过长连接的说法,而且还知道HTTP1.0协议不支持长连接,从HTTP1.1协议以后,连接默认都是长连接。但LZ终究觉得对于长连接一直懵懵懂懂的,有种抓不到关键点的感觉。

今天LZ通过一番研究,终于明白了这其中的奥秘。而之前,LZ也看过长连接相关的内容,但一直都是云里雾里的。这次之所以能在这么短的时间里搞清楚,和LZ自己技术的沉淀密不可分。因此,这里LZ借着这个机会,再次强调一下,千万不要试图去研究你研究了很久都整不明白的东西,或许是你的层次不到,也或许是你从未在实际的应用场景接触过,这种情况下你去研究,只会事倍功半,徒劳一番罢了。

回到正题,既然说是误解,那么LZ的误解到底是什么?

那就是LZ一直认为,HTTP连接分为长连接和短连接,而我们现在常用的都是HTTP1.1,因此我们用的都是长连接。

这句话其实只对了一半,我们现如今的HTTP协议,大部分都是1.1的,因此我们平时用的基本上都是长连接。但是前半句是不对的,HTTP协议根本没有长短连接这一说,也正因为误解了这个,导致LZ对于长连接一直不明不白,始终不得其要领,具体下面一段会说到。

网络上很多文章都是误人子弟,根本没有说明白这个概念。这里LZ要强调一下,HTTP协议是基于请求/响应模式的,因此只要服务端给了响应,本次HTTP连接就结束了,或者更准确的说,是本次HTTP请求就结束了,根本没有长连接这一说。那么自然也就没有短连接这一说了。

之所以网络上说HTTP分为长连接和短连接,其实本质上是说的TCP连接。TCP连接是一个双向的通道,它是可以保持一段时间不关闭的,因此TCP连接才有真正的长连接和短连接这一说

其实知道了以后,会觉得这很好理解。HTTP协议说到底是应用层的协议,而TCP才是真正的传输层协议,只有负责传输的这一层才需要建立连接。

一个形象的例子就是,拿你在网上购物来说,HTTP协议是指的那个快递单,你寄件的时候填的单子就像是发了一个HTTP请求,等货物运到地方了,快递员会根据你发的请求把货物送给相应的收货人。而TCP协议就是中间运货的那个大货车,也可能是火车或者飞机,但不管是什么,它是负责运输的,因此必须要有路,不管是地上还是天上。那么这个路就是所谓的TCP连接,也就是一个双向的数据通道。

因此,LZ现在甚至觉得,“HTTP连接”这个词就不应该出现,它只是一个应用层的协议,根本就没有所谓的连接这一说,就像FTP也是应用层的协议,但是你有听说过FTP连接吗?(恩,好像是听过,-_-,但你现在知道了,其实所谓的FTP连接,严格来说,依旧是TCP连接)

实际上,说HTTP请求和HTTP响应会更准确一些,而HTTP请求和HTTP响应,都是通过TCP连接这个通道来回传输的。

不管怎么说,一定要务必记住,长连接是指的TCP连接,而不是HTTP连接。

一个疑问

之前LZ一直对一件事有些模糊不清,首先是怎么样就算是把HTTP变成长连接了,是不是只要设置Connection为keep-alive就算是了?

如果是的话,那都说HTTP1.1默认是长连接,而观察我们平时开发的Web应用的HTTP头部,Connection也确实是keep-alive,那就是说我们大部分都是用的长连接,但是长连接不是一般用于交互比较频繁的应用吗?像我们这种普通的Web应用,比如博客园这种,或者我的个人博客这种,长连接有什么用?

如果有用那用处到底是什么,我们又不是客户端与服务器交互频繁的那种应用(毕竟你打开网页肯定要半天才打开另外一个吧),如果没用的话,那到底应不应该把Connection为keep-alive这个header值给改掉,从而改成短连接?

这个疑问,在LZ明白了长连接其实是指的TCP连接之后,基本上就明白了。而这个疑问,也正是LZ在“以前的误解”那一段所提到的,那个因为误解导致LZ一直搞不明白的问题。

为什么解决了上面那个误解之后,前面所说的这些疑问LZ都明白了?

因为长连接意味着连接会被复用,毕竟一直保持着连接不就是为了重复使用嘛。但如果长连接是指的HTTP的话,那就是说HTTP连接可以被重复利用,这个话听起来就感觉很别扭。之所以觉得别扭,其实就是LZ的一种直觉,没什么理论依据。而这种别扭的根源就在于,之前一直没有融会贯通的感觉,所以总感觉缺少点什么。不过这点疑惑,并没有影响LZ的工作,因此也就没深究过。

但现在好了,明白了长连接实际上是指的TCP连接,LZ瞬间自己就想明白了上面的那些问题。

第一个问题是,是不是只要设置Connection为keep-alive就算是长连接了?

当然是的,但要服务器和客户端都设置。

第二个问题是,我们平时用的是不是长连接?

这个也毫无疑问,当然是的。(现在用的基本上都是HTTP1.1协议,你观察一下就会发现,基本上Connection都是keep-alive。而且HTTP协议文档上也提到了,HTTP1.1默认是长连接,也就是默认Connection的值就是keep-alive)

第三个问题,也是LZ之前最想不明白的问题,那就是我们这种普通的Web应用(比如博客园,我的个人博客这种)用长连接有啥好处?需不需要关掉长连接而使用短连接?

这个问题LZ现在终于明白了,问题的答案是好处还是有的。

好处是什么?

首先,刚才已经说了,长连接是为了复用,这个在之前LZ就明白。那既然长连接是指的TCP连接,也就是说复用的是TCP连接。那这就很好解释了,也就是说,长连接情况下,多个HTTP请求可以复用同一个TCP连接,这就节省了很多TCP连接建立和断开的消耗。

比如你请求了博客园的一个网页,这个网页里肯定还包含了CSS、JS等等一系列资源,如果你是短连接(也就是每次都要重新建立TCP连接)的话,那你每打开一个网页,基本要建立几个甚至几十个TCP连接,这浪费了多少资源就不用LZ去说了吧。

但如果是长连接的话,那么这么多次HTTP请求(这些请求包括请求网页内容,CSS文件,JS文件,图片等等),其实使用的都是一个TCP连接,很显然是可以节省很多消耗的。

这样一解释,就很明白了,不知道大家看了这些解释感觉如何,反正LZ在自己想明白以后,有种豁然开朗的感觉。

另外,最后关于长连接还要多提一句,那就是,长连接并不是永久连接的。如果一段时间内(具体的时间长短,是可以在header当中进行设置的,也就是所谓的超时时间),这个连接没有HTTP请求发出的话,那么这个长连接就会被断掉。

这一点其实很容易理解,否则的话,TCP连接将会越来越多,直到把服务器的TCP连接数量撑爆到上限为止。现在想想,对于服务器来说,服务器里的这些个长连接其实很有数据库连接池的味道,大家都是为了节省连接重复利用嘛,对不对?

长轮询和短轮询

前面基本上LZ已经把长短连接说的差不多了,接下来说说长短轮询,今天也正是为了研究长短轮询,LZ才顺便研究了下长短连接这回事。

短轮询相信大家都不难理解,比如你现在要做一个电商中商品详情的页面,这个详情界面中有一个字段是库存量(相信这个大家都不陌生,随便打开淘宝或者京东都能找到这种页面)。而这个库存量需要实时的变化,保持和服务器里实际的库存一致。

这个时候,你会怎么做?

最简单的一种方式,就是你用JS写个死循环,不停的去请求服务器中的库存量是多少,然后刷新到这个页面当中,这其实就是所谓的短轮询。

这种方式有明显的坏处,那就是你很浪费服务器和客户端的资源。客户端还好点,现在PC机配置高了,你不停的请求还不至于把用户的电脑整死,但是服务器就很蛋疼了。如果有1000个人停留在某个商品详情页面,那就是说会有1000个客户端不停的去请求服务器获取库存量,这显然是不合理的。

那怎么办呢?

长轮询这个时候就出现了,其实长轮询和短轮询最大的区别是,短轮询去服务端查询的时候,不管库存量有没有变化,服务器就立即返回结果了。而长轮询则不是,在长轮询中,服务器如果检测到库存量没有变化的话,将会把当前请求挂起一段时间(这个时间也叫作超时时间,一般是几十秒)。在这个时间里,服务器会去检测库存量有没有变化,检测到变化就立即返回,否则就一直等到超时为止。

而对于客户端来说,不管是长轮询还是短轮询,客户端的动作都是一样的,就是不停的去请求,不同的是服务端,短轮询情况下服务端每次请求不管有没有变化都会立即返回结果,而长轮询情况下,如果有变化才会立即返回结果,而没有变化的话,则不会再立即给客户端返回结果,直到超时为止。 

这样一来,客户端的请求次数将会大量减少(这也就意味着节省了网络流量,毕竟每次发请求,都会占用客户端的上传流量和服务端的下载流量),而且也解决了服务端一直疲于接受请求的窘境。

但是长轮询也是有坏处的,因为把请求挂起同样会导致资源的浪费,假设还是1000个人停留在某个商品详情页面,那就很有可能服务器这边挂着1000个线程,在不停检测库存量,这依然是有问题的。

因此,从这里可以看出,不管是长轮询还是短轮询,都不太适用于客户端数量太多的情况,因为每个服务器所能承载的TCP连接数是有上限的,这种轮询很容易把连接数顶满。之所以举这个例子,只是因为大家肯定都会网购,所以这个例子比较通俗一点。

哪怕轮询解决不了获取库存这个问题,但只要大家明白了长短轮询的区别,这就足够了。实际上,据LZ自己平日里购物的观察,那个库存量应该是不会变的,这个例子纯属LZ个人的意淫,-_-。、

长轮询和长短连接的区别

这里简单说一下它们的区别,LZ这里只说最根本的区别。

第一个区别是决定的方式,一个TCP连接是否为长连接,是通过设置HTTP的Connection Header来决定的,而且是需要两边都设置才有效。而一种轮询方式是否为长轮询,是根据服务端的处理方式来决定的,与客户端没有关系。

第二个区别就是实现的方式,连接的长短是通过协议来规定和实现的。而轮询的长短,是服务器通过编程的方式手动挂起请求来实现的。

结语

好了,本文就到此为止吧。LZ写这篇文章,主要也是为了避免自己遗忘。说实话,写到最后了,LZ感觉对于它们的理解又进了一步,这就是写博客的好处吧。

 

这篇关于HTTP协议中的短轮询、长轮询、长连接和短连接 序言 最近刚到公司不到一个月,正处于熟悉项目和源码的阶段,因此最近经常会看一些源码。在研究一个项目的时候,源码里面用到了HTTP的长轮询。由于之前没太的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1135871

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

poj1330(LCA最近公共祖先)

题意:求最近公共祖先 思路:之前学习了树链剖分,然后我就用树链剖分的一小部分知识就可以解这个题目了,记录每个结点的fa和depth。然后查找时,每次将depth大的结点往上走直到x = y。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring>

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码