浏览器是如何访问互联网的呢?
首先人们会告诉浏览器一个网址,比如www.jd.com, 然后就可以通过TCP协议与服务器建立一个连接,通过这个连接通道给服务器发消息,消息格式是与服务器约定好了的。
服务器会按照约定返回整个页面的数据(HTML文档),当然也是通过**同一个**连接通道。
然后这个连接通道会被关闭。
浏览器与服务器的这种约定就叫**HTTP协议**
## 重复利用每个连接通道
随着互联网的发展,网页变得非常复杂,开始出现图片等,为了把图片得资源快速下载下来,需要通过TCP协议建立很多的连接通道,有些下载图片,有些下载CSS等。
我们知道TCP的连接提交的麻烦,需要3次握手和4次挥手。。
如果连接建立得较多,浪费极大。
那么能不能建立一个连接通道,并且不关闭?
可以协商出一个keep-alive机制,默认情况下,让TCP协议一直保持打开的连接通道,可以持续的在连接通道上发送消息。
如果长时间不发消息时,或者某一方明确要关闭连接,可以把连接通道关闭掉
这样,可以复用连接通道了。
## 只有纯数据,不用格式化文档
随着页面越来越大,人们对响应时间要求越来越高,大家希望能迅速的看到效果。
但是每次服务器会返回HTML文档给浏览器,导致浏览器需要刷新整个页面。
观察发现,每次从服务器收到的数据其实只有一丁点的变化,能否进行局部更新呢?
也就是说,装载过HTML文档之后,后续的操作,就只通过XML或者JSON这种纯粹的数据进行交流了。
具体流程如下:
用户在页面操作之后,整个页面不会刷新(浏览器的地址不会改变),JavaScript在背后让TCP建立一个通道,和服务器通信,获取更新的数据,然后局部更新。
不过这还有一个问题,JavaScript在发出HTTP请求之后,需要等待服务器把数据返回,这段时间内,浏览器是什么都干不了的。就像假死了一样。
可以**异步**:JavaScript发出HTTP请求之后,不等待服务器把数据返回,立刻干别的事情去了。等到服务器的数据回来了,浏览器再通知他处理。这就是AJAX
## 抛弃HTTP
完全抛弃的HTTP是不可能的,但是在某些场景下,比如说把桌面应用迁移到浏览器上的时候。
假设现在有个在线协作软件,多个人可以在同一个页面进行操作,如果想把每个人的鼠标位置广播给大家,这就非常的麻烦。
因为会向服务器发送数据非常频繁,但是每次发送的信息又非常的少。类似于x=100&y=200这样的东西。
如果每次都遵循HTTP协议,构建HTTP请求,会发现传递了太多的无用的东西
```
POST / HTTP/1.1
Host: localhost
User-Agent: .... 略...
Accept: text/html .... 略...
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost/test.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 9
x=20&y=70
```
而且在移动互联网时代,大家对实时性要求更高了,比如说股票信息、朋友圈更新等。
如果使用HTTP协议去经常**轮询**服务器,大部分时间是在做无用功。
能不能不局限HTTP协议呢?
大致总结一下:
- 不要HTTP的头
- 浏览器和服务器之间要能互相发送数据
这不就是socket吗?两个电脑之间建立了socket之后,想发什么数据都可以,数据格式自己定义。
于是应用层的WebSocket就出现了。
但是HTTP被应用得太广泛了,防火墙、缓存、代理等都是基于HTTP的。为了让大家能迅速支持WebSocket,还需要和HTTP保持一定的兼容性,
比如建立WebSocket的时候,可以使用HTTP
```
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Version: 13
```
这段话的意思是说:服务器,把 HTTP 升级为 Websocket 吧?
然后服务器回复:
```
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
```
服务器回复:我同意,以后我们就切换到 Websocket 协议开始通信了啊。
于是连接就建起来了, 接下来浏览器和服务器就可以双向通信了。
浏览器要是想发送数据, 就直接发送 x=20&y=70, 根本没有浪费流量的 HTTP header , 服务器有啥数据想给我, 也直接推送, 不用我去查询了。
不过WebSocket也是基于TCP协议的,请示就是建立在原来TCP连接的通道之上。