一、什么是长连接

HTTP1.1规定了默认保持长连接(HTTP persistent connection ,也有翻译为持久连接),数据传输完成了保持TCP连接不断开(不发RST包、不四次握手),等待在同域名下继续用这个通道传输数据;相反的就是短连接。

 HTTP首部的Connection: Keep-alive是HTTP1.0浏览器和服务器的实验性扩展,当前的HTTP1.1 RFC2616文档没有对它做说明,因为它所需要的功能已经默认开启,无须带着它,但是实践中可以发现,浏览器的报文请求都会带上它。如果HTTP1.1版本的HTTP请求报文不希望使用长连接,则要在HTTP请求报文首部加上Connection: close。《HTTP权威指南》提到,有部分古老的HTTP1.0 代理不理解Keep-alive,而导致长连接失效:客户端-->代理-->服务端,客户端带有Keep-alive,而代理不认识,于是将报文原封不动转给了服务端,服务端响应了Keep-alive,也被代理转发给了客户端,于是保持了“客户端-->代理”连接和“代理-->服务端”连接不关闭,但是,当客户端第发送第二次请求时,代理会认为当前连接不会有请求了,于是忽略了它,长连接失效。书上也介绍了解决方案:当发现HTTP版本为1.0时,就忽略Keep-alive,客户端就知道当前不该使用长连接。其实,在实际使用中不需要考虑这么多,很多时候代理是我们自己控制的,如Nginx代理,代理服务器有长连接处理逻辑,服务端无需做patch处理,常见的是客户端跟Nginx代理服务器使用HTTP1.1协议&长连接,而Nginx代理服务器跟后端服务器使用HTTP1.0协议&短连接。

在实际使用中,HTTP头部有了Keep-Alive这个值并不代表一定会使用长连接,客户端和服务器端都可以无视这个值,也就是不按标准来,譬如我自己写的HTTP客户端多线程去下载文件,就可以不遵循这个标准,并发的或者连续的多次GET请求,都分开在多个TCP通道中,每一条TCP通道,只有一次GET,GET完之后,立即有TCP关闭的四次握手,这样写代码更简单,这时候虽然HTTP头有Connection: Keep-alive,但不能说是长连接。正常情况下客户端浏览器、web服务端都有实现这个标准,因为它们的文件又小又多,保持长连接减少重新开TCP连接的开销很有价值。

以前使用libcurl做的上传/下载,就是短连接,抓包可以看到:1、每一条TCP通道只有一个POST;2、在数据传输完毕可以看到四次握手包。只要不调用curl_easy_cleanup,curl的handle就可能一直有效,可复用。这里说可能,因为连接是双方的,如果服务器那边关掉了,那么我客户端这边保留着也不能实现长连接。

如果是使用windows的WinHTTP库,则在POST/GET数据的时候,虽然我关闭了句柄,但这时候TCP连接并不会立即关闭,而是等一小会儿,这时候是WinHTTP库底层支持了跟Keep-alive所需要的功能:即便没有Keep-alive,WinHTTP库也可能会加上这种TCP通道复用的功能,而其它的网络库像libcurl则不会这么做。以前观察过WinHTTP库不会及时断开TCP连接

二、长连接的过期时间

客户端的长连接不可能无限期的拿着,会有一个超时时间,服务器有时候会告诉客户端超时时间,譬如:

上图中的Keep-Alive: timeout=20,表示这个TCP通道可以保持20秒。另外还可能有max=XXX,表示这个长连接最多接收XXX次请求就断开。对于客户端来说,如果服务器没有告诉客户端超时时间也没关系,服务端可能主动发起四次握手断开TCP连接,客户端能够知道该TCP连接已经无效;另外TCP还有心跳包来检测当前连接是否还活着,方法很多,避免浪费资源。

三、长连接的数据传输完成识别

使用长连接之后,客户端、服务端怎么知道本次传输结束呢?两部分:1是判断传输数据是否达到了Content-Length指示的大小;2动态生成的文件没有Content-Length,它是分块传输(chunked),这时候就要根据chunked编码来判断,chunked编码的数据在最后有一个空chunked块,表明本次传输数据结束。更细节的介绍可以看这篇文章

四、并发连接数的数量限制

在web开发中需要关注浏览器并发连接的数量,RFC文档说,客户端与服务器最多就连上两通道,但服务器、个人客户端要不要这么做就随人意了,有些服务器就限制同时只能有1个TCP连接,导致客户端的多线程下载(客户端跟服务器连上多条TCP通道同时拉取数据)发挥不了威力,有些服务器则没有限制。浏览器客户端就比较规矩,知乎这里有分析,限制了同域名下能启动若干个并发的TCP连接去下载资源。并发数量的限制也跟长连接有关联,打开一个网页,很多个资源的下载可能就只被放到了少数的几条TCP连接里,这就是TCP通道复用(长连接)。如果并发连接数少,意味着网页上所有资源下载完需要更长的时间(用户感觉页面打开卡了);并发数多了,服务器可能会产生更高的资源消耗峰值。浏览器只对同域名下的并发连接做了限制,也就意味着,web开发者可以把资源放到不同域名下,同时也把这些资源放到不同的机器上,这样就完美解决了。

五、容易混淆的概念——TCPkeep aliveHTTPKeep-alive

TCP的keep alive是检查当前TCP连接是否活着;HTTP的Keep-alive是要让一个TCP连接活久点。它们是不同层次的概念。

TCP keep alive的表现:

当一个连接“一段时间”没有数据通讯时,一方会发出一个心跳包(Keep Alive包),如果对方有回包则表明当前连接有效,继续监控。

这个“一段时间”可以设置。

WinHttp库的设置:

WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL
Sets the interval, in milliseconds, to send a keep-alive packet over the
connection. The default interval is 30000 (30 seconds). The minimum interval is
15000 (15 seconds). Using WinHttpSetOption to set a value lower than 15000 will
return with ERROR_INVALID_PARAMETER.

libcurl的设置:

http://curl.haxx.se/libcurl/c/curl_easy_setopt.html

CURLOPT_TCP_KEEPALIVE

Pass a long. If set to 1, TCP keepalive probes will be sent.
The delay and frequency of these probes can be controlled by the
CURLOPT_TCP_KEEPIDLE and CURLOPT_TCP_KEEPINTVL options, provided the operating
system supports them. Set to 0 (default behavior) to disable keepalive probes
(Added in 7.25.0).

CURLOPT_TCP_KEEPIDLE

Pass a long. Sets the delay, in seconds, that the operating
system will wait while the connection is idle before sending keepalive probes.
Not all operating systems support this option. (Added in 7.25.0)

CURLOPT_TCP_KEEPINTVL

Pass a long. Sets the interval, in seconds, that the
operating system will wait between sending keepalive probes. Not all operating
systems support this option. (Added in 7.25.0)

CURLOPT_TCP_KEEPIDLE是空闲多久发送一个心跳包,CURLOPT_TCP_KEEPINTVL是心跳包间隔多久发一个。

打开网页抓包,发送心跳包和关闭连接如下:

从上图可以看到,大概过了44秒,客户端发出了心跳包,服务器及时回应,本TCP连接继续保持。到了空闲60秒的时候,服务器主动发起FIN包,断开连接。

六、HTTP 流水线技术

使用了HTTP长连接(HTTP persistent connection )之后的好处,包括可以使用HTTP 流水线技术(HTTP
pipelining,也有翻译为管道化连接),它是指,在一个TCP连接内,多个HTTP请求可以并行,下一个HTTP请求在上一个HTTP请求的应答完成之前就发起。从wiki上了解到这个技术目前并没有广泛使用,使用这个技术必须要求客户端和服务器端都能支持,目前有部分浏览器完全支持,而服务端的支持仅需要:按HTTP请求顺序正确返回Response(也就是请求&响应采用FIFO模式),wiki里也特地指出,只要服务器能够正确处理使用HTTP pipelinning的客户端请求,那么服务器就算是支持了HTTP pipelining。

由于要求服务端返回响应数据的顺序必须跟客户端请求时的顺序一致,这样也就是要求FIFO,这容易导致Head-of-line
blocking:第一个请求的响应发送影响到了后边的请求,因为这个原因导致HTTP流水线技术对性能的提升并不明显(wiki提到,这个问题会在HTTP2.0中解决)。另外,使用这个技术的还必须是幂等的HTTP方法,因为客户端无法得知当前已经处理到什么地步,重试后可能发生不可预测的结果。POST方法不是幂等的:同样的报文,第一次POST跟第二次POST在服务端的表现可能会不一样。

在HTTP长连接的wiki中提到了HTTP1.1的流水线技术对RFC规定一个用户最多两个连接的指导意义:流水线技术实现好了,那么多连接并不能提升性能。我也觉得如此,并发已经在单个连接中实现了,多连接就没啥必要,除非瓶颈在于单个连接上的资源限制迫使不得不多开连接抢资源。

目前浏览器并不太重视这个技术,毕竟性能提升有限。

本文所在:http://www.cnblogs.com/cswuyg/p/3653263.html

七、学习资料

1、HTTP Keep-Alive模式:http://www.cnblogs.com/skynet/archive/2010/12/11/1903347.html

2、浏览器的并发请求限制:http://www.zhihu.com/question/20474326

3、RFC文档 connection部分:http://tools.ietf.org/html/rfc2616#page-44

4、C/C++网络编程中的TCP保活: http://blog.csdn.net/weiwangchao_/article/details/7225338

5、HTTP persistent
connection: http://en.wikipedia.org/wiki/HTTP_persistent_connection

6、HTTP pipelining:http://en.wikipedia.org/wiki/HTTP_pipelining

7、Head-of-line
blocking:http://en.wikipedia.org/wiki/Head-of-line_blocking

8、《HTTP权威指南》第四章 连接管理

ps: 2014.7.27 第二次补充:阅读完《HTTP权威指南》第四章,补充长连接的理论知识。

HTTP长连接短连接的更多相关文章

  1. nginx 代理tcp长连接短连接配置

    https://blog.csdn.net/tayinyinyueyue/article/details/78932697 nginx使用ngx_stream_core_module模块代理tcp长连 ...

  2. 长连接 短连接 RST报文

    https://baike.baidu.com/item/短连接 短连接(short connnection)是相对于长连接而言的概念,指的是在数据传送过程中,只在需要发送数据时,才去建立一个连接,数 ...

  3. MySQL 线程池&连接池&长连接&短连接

    线程池 简介 1.mysql每连接每线程,mysql都分配一个单独的线程,该线程处理客户端发来的所有命令 2.每个线程会占用一定的系统资源,线程数越多消耗的系统资源也越多 3.线程的创建和销毁有一定的 ...

  4. java socket 长连接 短连接

    长连接 是一旦一个客户端登陆上服务器,其与服务器之间的连接就不关闭,不管他们之间进行了多少次交易,直到客户端退出登陆或网络出现故障.这种技术在联机交易系统实现有利于提高效率. 短连接是客户端每发一个请 ...

  5. Socket 长连接 短连接 心跳 JAVA SOCKET编程

    简单解释就是: 短连接:建立连接,发送数据包.关闭连接 长连接:建立连接.发送数据包,发送心跳包,发送数据包,发送心跳包.发送心跳包. ..... 所以又频繁的数据收发的话.短连接会频繁创建TCP连接 ...

  6. [Golang] 从零開始写Socket Server(3): 对长、短连接的处理策略(模拟心跳)

    通过前两章,我们成功是写出了一套凑合能用的Server和Client,并在二者之间实现了通过协议交流.这么一来,一个简易的socket通讯框架已经初具雏形了,那么我们接下来做的.就是想办法让这个框架更 ...

  7. [PHP] time_wait与长连接短连接

    服务端上查看tcp连接的建立情况,直接使用netstat命令来统计,看到了很多的time_wait状态的连接.这些状态是tcp连接中主动关闭的一方会出现的状态.该服务器是nginx的webserver ...

  8. tcp & 长连接 短连接

    参考文档: tcp协议 http://blog.chinaunix.net/uid-26833883-id-3627644.html 长连接和短连接 http://blog.csdn.net/free ...

  9. http 长连接 & 短连接

    1.意义 同一个TCP连接来发送和接收多个HTTP请求/应答,而不是为每一个新的请求/应答打开新的连接的方法. 2.优 较少的CPU和内存的使用 允许请求和应答的HTTP pipelining 降低网 ...

随机推荐

  1. Android UI基础之五大布局

    Android  UI基础之五大布局 Android的界面是有布局和组件协同完成的,布局好比是建筑里的框架,而组件则相当于建筑里的砖瓦.组件按照布局的要求依次排列,就组成了用户所看见的界面.Andro ...

  2. 如何远程断点调试本地localhost项目

    前言 对于一般开发网站的IDE自带的服务器是都跑在 localhost 地址上的.(如下图的asp.net) 而这种地址是只能在本机通过 localhost 或 127.0.0.1 地址访问到,而无法 ...

  3. 第一章 Javscript的数据类型

      任何编程语言,都会讲到数据类型,那么我在这里也简述下Js的数据类型,在js里判断一个变量的数据类型用typeof() 简单数据类型undefined: 代表一切未知的事物,啥都没有,无法想象,代码 ...

  4. 微信第一个“小程序”亮相:不是APP胜似APP!

    前天晚上,微信终于推出了“小程序”功能.看过效果演示之后,网友表示,好多App可以卸载了! 据了解,微信“小程序”已首批开放给200名拥有微信服务号的开发者进行内测,而且目前开发者发布的小程序无法在用 ...

  5. node 日志

    我们主动控制的log4js,还有一些日志是继承好的,错误日志了,进程日志了,请求日志了. 1. var express = require('express');var logger = requir ...

  6. Node on Mac 初步

    安装node之前 1.之前在windows平台上安装node,直接下载一个安装文件得了.但是mac osx是基于unix架构的嘛,跟linux很像啊. 在linux上安装我们多习惯用命令行工具安装啊, ...

  7. easyui中tree控件添加自定义图标icon

    来源于:http://blog.163.com/lintianhuanhai@126/blog/static/165587366201421704420256/ <!DOCTYPE html&g ...

  8. C# 域用户操作(转)

    转自:http://www.sobnb.com/u/92/20081406091447.html using System; using System.DirectoryServices;   nam ...

  9. iOS边练边学--Http网络再学习,简单介绍

    一.URL 什么是URL URL中常见的协议 二.Http Http的基本通信过程 发送Http请求的方法 GET 和 POST 对比 GET 和 POST 的选择 三.iOS中的Http学习 iOS ...

  10. webform中的验证控件及两个应用技巧

    一.非空验证--RequiredFiledValidator <一>属性: ErrorMessage--验证出错后的提示信息 ControlToValidate--要验证的控件的ID Di ...