Page 267 - Web性能权威指南
P. 267

var ws = new WebSocket('wss://example.com/socket');
                   ws.onopen = function () {
                     subscribeToApplicationUpdates(function(evt) { ➊
                       if (ws.bufferedAmount == 0) ➋
                         ws.send(evt.data); ➌
                     });
                   };

               ➊ 预订应用更新(如游戏状态更新)
               ➋ 检查客户端缓冲的数据量
               ➌ 如果缓冲是空的,发送下一次更新

               前面的例子是要向服务器发送应用数据,但前提是客户端缓冲区已经没有之前待发
               送的数据了。为什么非要做这个检查?所有 WebSocket 消息都会按照它们在客户端
               排队的次序逐个发送。因此,大量排队的消息,甚至一个大消息,都可能导致排在
               它后面的消息延迟——队首阻塞!
               为解决这个问题,应用可以将大消息切分成小块,通过监控 bufferedAmount 的值来
               避免队首阻塞。甚至还可以实现自己的优先队列,而不是盲目都把它们送到套接字
               上排队。


                          很多应用都会生成多种消息:有高优先级的更新,也有低优先级的更新。
                          前者比如流量控制消息,后者比如后台传输。要实现最优化传输,应用必
                          须关心任意时刻在套接字上排队的是什么消息!


               17.1.4 子协议协商

               WebSocket 协议对每条消息的格式事先不作任何假设:仅用一位标记消息是文本还是
               二进制,以便客户端和服务器有效地解码数据,而除此之外的消息内容就是未知的。

               此外,与 HTTP 或 XHR 请求不同——它们是通过每次请求和响应的 HTTP 首部来
               沟通元数据,WebSocket 并没有等价的机制。因此,如果需要沟通关于消息的元数
               据,客户端和服务器必须达成沟通这一数据的子协议。

               •   客户端和服务器可以提前确定一种固定的消息格式,比如所有通信都通过 JSON
                 编码的消息或者某种自定义的二进制格式进行,而必要的元数据作为这种数据结
                 构的一个部分。
               •   如果客户端和服务器要发送不同的数据类型,那它们可以确定一个双方都知道的
                 消息首部,利用它来沟通说明信息或有关净荷的其他解码信息。




               256   |   第 17 章
   262   263   264   265   266   267   268   269   270   271   272