误人子弟的网络,谈谈HTTP协议中的短轮询、长轮询、长连接和短连接

发布时间:2016-04-14 00:09:00作者:左潇龙阅读(2966 )评论(55)

    引言

      

      最近刚到公司不到一个月,正处于熟悉项目和源码的阶段,因此最近经常会看一些源码。在研究一个项目的时候,源码里面用到了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感觉对于它们的理解又进了一步,这就是写博客的好处吧。

      写了这么多,最后给自己打个小广告(莫要拍砖,-_-),LZ每周都会在直播网站做直播,地址在博客左侧,如果想要了解直播的时间,可以加LZ的交流群,群号同样在博客左侧。直播的内容主要是带大家一起看源码,看书,或者解答各种疑难杂症的问题,包括但不限于技术、职场、人生、情感等。

      最最后,如果你有任务调度框架的需求,请考虑一下niubi-job,多的这里就不介绍了,请看LZ的博文。

      广告时间结束!


    版权声明:本文版权归作者(左潇龙)所有,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

    35
    精彩
    0
    感动
    0
    搞笑
    0
    开心
    0
    愤怒
    0
    无聊
    0
    灌水
    0
    惊讶
#1楼     时间:2016-04-14 00:29:00      来源:wzx_xle
真是茅舍顿开啊,一次请求就是一次请求,没什么保持不保持的概念,只有TCP连接长短的概念。之前还以为是浏览器优化做了TCP连接复用呢,原来是HTTP协议导致的。
#2楼     时间:2016-04-14 08:33:00      来源:天天
我感觉轮训就是客户定时访问,例如调用setInterval每隔1秒钟客户端访问服务器一次。当时间设置“足够短”,就可以实现“实时”。

function chksvr()
{
$.get("test.aspx");
}
setInterval("chksvr",1000);

长连接就是通过返回值访问。例如chksvr2通过其返回值会再次调用chksvr2,建立一个连接。

function chksvr2() {
$.post("test2.aspx",
function (data, status) {
//处理数据
chksvr2();
}, );
}
不过,chksvr2处理中,因为服务器没有数据不用返回,所以test2.aspx 不是普通的继承Page的类,而是继承IHttpAsyncHandler接口实现。
另外,采用第二种方式时,会有请求一直pending那里,但是微软的SingalR却不会,不知道Singal怎么实现的。
#3楼     时间:2016-04-14 08:54:00      来源:Holt_Vong
LZ最好还是再细致理解清楚好点。
HTTP协议是基于请求/响应模式的,因此只要服务端给了响应,本次HTTP连接就结束了?

基于 Iframe 及 htmlfile 的流(streaming)方式
iframe 是很早就存在的一种 HTML 标记, 通过在 HTML 页面里嵌入一个隐蔵帧,然后将这个隐蔵帧的 SRC 属性设为对一个长连接的请求,服务器端就能源源不断地往客户端输入数据。

如果是上面这种方式,即使服务端有所响应,请求依然没有结束,服务端可以做多次的响应。

参考:
www.ibm.com/developerworks/cn/web/wa-lo-comet/
#4楼     时间:2016-04-14 09:09:00      来源:轮回
总结的好
#5楼     时间:2016-04-14 09:18:00      来源:jerry.li
太啰嗦了。
#6楼     时间:2016-04-14 09:42:00      来源:左潇龙
@ Holt_Vong
为什么没有像你说的,去”细致理解清楚“。原因文中已经说了,不要去研究你看了很久也不明白的东西,那说明你的层次不到,或者你实际上从未遇到过,所以你很难理解。
这个我在之前就看到了,但我依然不认为这个所谓的iframe流方式,是真正意义上的可以在一次HTTP请求以后,发送多次响应,多半也是和长轮询一样,只是服务端做的一种手段,造成了”返回了多次响应“的这种表象而已。
当然了,或许这会是我的又一个误解,但我觉得等真正用到的时候,自然会解开这个疑惑的,不要强求。
不过,如果你能不要只说一句结论发个连接,而是在下面用自己的理解解释清楚的话,那我也会强求一下的,看看我能不能消化掉这个流模式,-_-。
#7楼     时间:2016-04-14 09:47:00      来源:heguo
受益匪浅
#8楼     时间:2016-04-14 09:48:00      来源:左潇龙
@ 天天
我不太清楚你所说的IHttpAsyncHandler和SingalR是什么,但是我只看你代码的话,我觉得这两段代码都只是短轮询而已。
#9楼     时间:2016-04-14 09:49:00      来源:左潇龙
@ 轮回
@wzx_xle
谢谢支持,-_-。
#10楼     时间:2016-04-14 09:50:00      来源:牛顿的小脑
恩,写的挺好的哈,多分享更多。
#11楼     时间:2016-04-14 09:57:00      来源:誤人子弟
#12楼     时间:2016-04-14 10:06:00      来源:醉心
太能侃了。。。
#13楼     时间:2016-04-14 10:31:00      来源:jerry_0824
~感谢分享~
#14楼     时间:2016-04-14 10:48:00      来源:Genius Zhang
感觉是老太在拉家常
#15楼     时间:2016-04-14 10:49:00      来源:催夜凉风
在科比最后一战的时候,突然对短连接和长连接有了新的认识,感谢博主!
#16楼     时间:2016-04-14 11:35:00      来源:唱歌的小猫
首先楼主能够不画图,通过文字就能把这几个名词说清楚很不容易了。我也清晰了很多。
其次,针对@天天提的问题,我觉得长短轮训的区别跟客户端和服务器端都有关系。不是说服务器端把请求挂起了就是长轮训,假如这个时候客户端再继续去请求,那么这个长连接就失去了意义(我理解的长连接是:客户端请求---服务器回应。中间的时间比我们正常打开网址服务器立马返回请求的时间要长,具体多长呢,最长就是连接超时。在这期间客户端不需要再次发送请求)
#17楼     时间:2016-04-14 12:09:00      来源:鸿鹄奥斯
http 和 https啥区别
#18楼     时间:2016-04-14 12:13:00      来源:沈赟
谢谢分享
#19楼     时间:2016-04-14 12:35:00      来源:17℃蓝
@ 天天
一般通过什么实现挂起?sleep吗?
#20楼     时间:2016-04-14 13:11:00      来源:czcz1024
@ 左潇龙
引用在这个时间里,服务器会去检测库存量有没有变化,检测到变化就立即返回,否则就一直等到超时为止。

不是这样的吧,这个请求过来,就hold住了,不返回,他自己也不在那检测。而是另一个请求的,比如购买,会导致这个值变化,然后让之前的那个请求返回
#21楼     时间:2016-04-14 13:50:00      来源:罗伟888
实时显示变化的数据到客户端浏览器确实是个头疼的问题。在供电系统的监测上,直接用了socket,那也是因为需监控的客户端不会太多。
一直想有时间好好研究下百度云推送、微信和手机之间的“长连接”,也一直没顾上,有了解的朋友请不吝赐教!
#22楼     时间:2016-04-14 14:01:00      来源:LouisGuo
#23楼     时间:2016-04-14 14:14:00      来源:i技术宅
感谢分享
#24楼     时间:2016-04-14 14:18:00      来源:阿萨德12321
不得不来顶一个 豁然开朗啊
#25楼     时间:2016-04-14 14:27:00      来源:幻天芒
很清晰,易懂。
#26楼     时间:2016-04-14 15:33:00      来源:我为程序员自豪
@ 罗伟888
可以用websocket推送
#27楼     时间:2016-04-14 15:44:00      来源:FerventDesert
写的很好,不过建议博主稍微修饰一下文风,有些话重复的有点多,让读者看着累
#28楼     时间:2016-04-14 15:47:00      来源:紫寻落
web端: 轮询 、长连接、 推送(html5) 说说优缺点、应用场景
#29楼     时间:2016-04-14 15:57:00      来源:Arik lee
感谢分线个,赞一个,茅塞顿开了。
#30楼     时间:2016-04-14 17:34:00      来源:luzemin
only you ~
#31楼     时间:2016-04-14 18:10:20      来源:深圳市网友

顶一下吧,不过你这个富文本评论控件实在有点惨不忍睹

#32楼     时间:2016-04-14 19:00:19      来源:左潇龙
@深圳市网友

顶一下吧,不过你这个富文本评论控件实在有点惨不忍睹

原谅我,0-0。

#33楼     时间:2016-04-14 19:28:00      来源:xmodygetz
计算机和计算机怎么通信?
TCP/IP 当然还有udp等等
需要一种叫做浏览器的程序,拥有固定的错误信息标示,并且告诉对方自身的设置和环境.
增加一个叫做http的层次吧,用http头传递一些额外信息
每次都建立tcp/ip需要3次握手,浪费资源.
持久连接(http1.1)
明文传输不安全
ssl/tls
http只能由客户端请求服务器,但是我需要监控服务器中的状态改变!
websocket
#34楼     时间:2016-04-14 19:53:00      来源:#张志豪#
醍醐灌顶
#35楼     时间:2016-04-14 20:33:00      来源:无尽的数字眩晕症
心中的一块石头终于放下了 :)
感谢楼主分享
#36楼     时间:2016-04-15 08:59:00      来源:benzero
该用絮絮叨叨还是娓娓道来评价LZ的风格呢-_-!
#37楼     时间:2016-04-15 15:02:00      来源:Nabulio
写的很好帮助很大
#38楼     时间:2016-04-15 15:22:00      来源:狼大人
写的非常好!
#39楼     时间:2016-04-15 16:09:00      来源:张凡文
只要搞清楚HTTP的本质,就不会有这种误解了。。

另外,搞研究最好的办法就是直接观察。比如想看看HTTP和TCP/IP是如何工作的,打开wireshark,然后打开一个网站,分析一下TCP和HTTP包就明白了。
#40楼     时间:2016-04-17 00:13:00      来源:TLXXM
#41楼     时间:2016-04-18 15:49:00      来源:*逍遥游*
qq群在哪?
#42楼     时间:2016-04-19 13:25:00      来源:论谁是英雄
有点意思。
#43楼     时间:2016-04-19 20:43:00      来源:紫川帝林
了解了不少,言简意赅,通俗易懂!
#44楼     时间:2016-04-27 10:45:51      来源:杭州市网友

写的很好

#45楼     时间:2016-04-28 14:48:00      来源:柳qing
讲的还挺好的 ~
#46楼     时间:2016-05-05 15:24:00      来源:Yangtze扬子
博主表达能力不错,不管理解深浅/完备与否,看得出来是自己的东西了。
另外,对 “不要去研究你看了很久也不明白的东西,那说明你的层次不到。。。但我觉得等真正用到的时候,自然会解开这个疑惑的” 
这点非常认可。
#47楼     时间:2016-05-05 15:28:00      来源:菜鸟要起飞
以前看斗鱼 都是找dota2看,关注楼主了,以后上斗鱼好好学习
#48楼     时间:2016-05-17 12:48:49      来源:泉州市网友

关于长连接、连接复用,可以看看HTTP2,HTTP1确实是不存在网络层的连接复用。~LZ加油,喜欢你的小说:)

#49楼     时间:2016-06-03 16:19:42      来源:西安市网友

LZ,可以当一名好的教师了

#50楼     时间:2016-08-17 08:00:39      来源:淄博市网友

lunxun zhege jaingde bijiaohao

#51楼     时间:2016-08-18 17:37:19      来源:扬州市网友

语言简练点,更好

#52楼     时间:2016-12-07 10:28:27      来源:杭州市网友

啰嗦了点

#53楼     时间:2016-12-07 10:28:43      来源:杭州市网友

配上图更好

#54楼     时间:2017-05-06 12:46:00      来源:大兄弟竹子
还是学到了,支持
#55楼     时间:2018-01-21 13:32:30      来源:111111
发表评论

站内搜索

最新评论