HTTP 和 Websocket | 青训营笔记

140 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天

服务器主动发消息给客户端(看起来像也行)

那么聪明的你脑袋里相比已经有个大概了,没错:要么傻乎乎的使用 HTTP 轮询,要么就换用 ws

那么你生的再聪明一点(得罪你咩!)就一定会知道,HTTP 轮询亦有优劣之分:

普通 HTTP 持续轮询

我不断请求服务器,无响应就不做任何显示,有响应再说,这样用户直观感受就是好像从服务器那边收到了信息。

但是这样首先是占用了带宽,还增大了下游服务器的负载

其次是为了不过分请求,会设置 HTTP 请求之间的间隔,这会造成较为明显的卡顿

长轮询

说实在话,一般扫码场景这个就绰绰有余了

简单来说,就是大幅增加原来的请求超时时间,原本可能 3s 无应答就重新发送,现在改成 30s,那么在这个过程中,服务器收到扫码就返回响应,未收到就阻塞至超时,然后客户端重新发送请求。

像这种发起一个请求,在较长时间内等待服务器响应的机制,就是所谓的长训轮机制。我们常用的消息队列RocketMQ中,消费者去取数据时,也用到了这种方式。

像这种,在用户不感知的情况下,服务器将数据推送给浏览器的技术,就是所谓的服务器推送 技术,它还有个毫不沾边的英文名,comet 技术,大家听过就好。

当然,这个过程明眼人都看出来了,像扫码这样一段时间内就一次操作的环节可以这么干,可要是大型游戏,大量数据会从服务器发往客户端,这下该怎么办呢

websocket

我们知道TCP连接的两端,同一时间里双方都可以主动向对方发送数据。这就是所谓的全双工

而现在使用最广泛的HTTP1.1,也是基于TCP协议的,同一时间里,客户端和服务器只能有一方主动发数据,这就是所谓的半双工

也就是说,好好的全双工TCP,被HTTP用成了半双工。

为什么?

这是由于HTTP协议设计之初,考虑的是看看网页文本的场景,能做到客户端发起请求再由服务器响应,就够了,根本就没考虑网页游戏这种,客户端和服务器之间都要互相主动发大量数据的场景。

所以为了更好的支持这样的场景,我们需要另外一个基于TCP的新协议

于是新的应用层协议websocket就被设计出来了。

大家别被这个名字给带偏了。虽然名字带了个socket,但其实socket和websocket之间,就跟雷峰和雷峰塔一样,二者接近毫无关系

总结

  • TCP协议本身是全双工的,但我们最常用的HTTP1.1,虽然是基于TCP的协议,但它是半双工的,对于大部分需要服务器主动推送数据到客户端的场景,都不太友好,因此我们需要使用支持全双工的websocket协议。
  • 在HTTP1.1里。只要客户端不问,服务端就不答。基于这样的特点,对于登录页面这样的简单场景,可以使用定时轮询或者长轮询的方式实现服务器推送(comet)的效果。
  • 对于客户端和服务端之间需要频繁交互的复杂场景,比如网页游戏,都可以考虑使用websocket协议。
  • websocket和socket几乎没有任何关系,只是叫法相似。
  • 正因为各个浏览器都支持HTTP协议,所以websocket会先利用HTTP协议加上一些特殊的header头进行握手升级操作,升级成功后就跟HTTP没有任何关系了,之后就用websocket的数据格式进行收发数据。