HTTP 长连接和持久连接

283 阅读4分钟

持久连接

持久连接(Persistent Connection):尽可能复用同一个连接,客户端发送一个请求,服务端完成请求响应,该连接也不会中断,客户端继续发送请求仍然使用这个连接,直到到达设置的max 请求次数,或者到达连接设置的timeout。

HTTP 协议采用 请求-应答 模式:

  • 普通模式:每个请求/应答客户和服务器都要新建一个连接,完成之后立即断开连接
  • Keep-Alive 模式:该功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive 功能避免了建立或者重新建立连接

在 HTTP/1.0 版本中,如果客户端浏览器支持 Keep-Alive ,那么就在 HTTP 请求头中添加一个字段 Connection: Keep-Alive,当服务器收到附带有 Connection: Keep-Alive 的请求时,它也会在响应头中添加一个同样的字段来使用 Keep-Alive 。这样一来,客户端和服务器之间的 HTTP 连接就会被保持,不会断开(超过 Keep-Alive 规定的时间,意外断电等情况除外),当客户端发送另外一个请求时,就使用这条已经建立的连接。

在 HTTP/1.1 版本中,默认情况下所有连接都被保持,如果加入 Connection: close 才关闭。目前大部分浏览器都使用 HTTP 1.1 协议,也就是说默认都会发起 Keep-Alive 的连接请求了,所以是否能完成一个完整的 Keep-Alive 连接就看服务器设置情况。

注意事项:

  • HTTP Keep-Alive 简单来说就是保持当前的 TCP 连接,避免了重新建立连接
  • HTTP 长连接不可能一直保持,例如 Keep-Alive: timeout=5, max=100,表示这个 TCP 通道可以保持 5 秒,且该长连接最多接收 100 次请求就断开
  • HTTP 是无状态协议,意味着每个请求都是独立的,Keep-Alive 没能改变这个结果

❓ 使用长连接后,客户端和服务端如何知道本次传输结束呢?

  1. 判断传输数据是否达到了 Content-Length 指示的大小
  2. 动态生成的文件采用分块传输的方式传输(Transfer-Encoding: chunked),这时候就要根据 chunked 编码来判断,chunked 编码的数据在最后有一个空 chunked 块,表明本次传输数据结束

转自(tsejx.github.io/javascript-…

长连接

长轮询(long polling)是与服务器保持持久连接的最简单的方式,它不使用任何特定的协议,例如 WebSocket 或者 Server Sent Event。

它很容易实现,在很多场景下也很好用。了解长轮询前,我们先看看常规轮询(polling)。

常规轮询

从服务器获取新信息的最简单的方式是定期轮询。也就是说,定期向服务器发出请求:“你好,我在这儿,你有关于我的任何信息吗?”例如,每 10 秒一次。

作为响应,服务器首先通知自己,客户端处于在线状态,然后 —— 发送目前为止的消息包。

这可行,但是也有些缺点:

  1. 消息传递的延迟最多为 10 秒(两个请求之间)。
  2. 即使没有消息,服务器也会每隔 10 秒被请求轰炸一次,即使用户切换到其他地方或者处于休眠状态,也是如此。就性能而言,这是一个很大的负担。

因此,如果我们讨论的是一个非常小的服务,那么这种方式可能可行,但总的来说,它需要改进。

长轮询

所谓“长轮询”是轮询服务器的一种更好的方式。

它也很容易实现,并且可以无延迟地传递消息。

其流程为:

  1. 请求发送到服务器。
  2. 服务器在有消息之前不会关闭连接。
  3. 当消息出现时 —— 服务器将对其请求作出响应。
  4. 浏览器立即发出一个新的请求。

对于此方法,浏览器发出一个请求并与服务器之间建立起一个挂起的(pending)连接的情况是标准的。仅在有消息被传递时,才会重新建立连接。

长轮询的golang 实现(www.xiayinchang.top/post/46e950…

其他

除此之外,还有websocket、screaming 可以实现长连接通信,甚至实现全双工通信。