|
马上注册登陆,结交更多好友,享用更多功能,让你轻松玩转社区
您需要 登录 才可以下载或查看,没有账号?用户注册
x
这是由于HTTP协议设计之初,考虑的是看看页文本的场景,能做到客户端发起请求再由服务器响应,就够了,根本就没考虑页游戏这种,客户端和服务器之间都要互相主动发大量数据的场景。?平时我们打开页,比如购物某宝。都是点一下列表商品,跳转一下页就到了商品详情。域名IP查询的具体问题可以到我们网站了解一下,也有业内领域专业的客服为您解答问题,为成功合作打下一个良好的开端!
从HTTP协议的角度来看,就是点一下页上的某个按钮,前端发一次HTTP请求,返回一次HTTP响应。
这种由客户端主动请求,服务器响应的方式也满足大部分页的功能场景。
但有没有发现,这种情况下,服务器从来就不会主动给客户端发一次消息。
就像你喜欢的女生从来不会主动找你一样。
但如果现在,你在刷页的时候右下角突然弹出一个小广告,提示你【一个人在家偷偷才能玩哦】。
求知,好学,勤奋,这些刻在你DNA里的东西都动起来了。
你点开后发现。
长相平平奇的古某提示你"道士9条狗,全服横着走"。
影帝某辉老师跟你说"系兄弟就来砍我"。
来都来了,你就选了个角色进到了游戏界面里。
这时候,上来就是一个小怪,从远处走来,然后疯狂拿木棒子抽你。
你全程没点任何一次鼠标。服务器就自动将怪物的移动数据和数据源源不断发给你了。
这…太暖心了。
感动之余,问题就来了,
像这种看起来服务器主动发消息给客户端的场景,是怎么做到的
在真正回答这个问题之前,我们先来聊下一些相关的知识背景。
使用HTTP不断轮询
其问题的痛点在于,怎么样才能在用户不做任何操作的情况下,页能收到消息并发生变更。
比较常见的解决方案是,页的前端代码里不断定时发HTTP请求到服务器,服务器收到请求后给客户端响应消息。
这其时一种伪服务器推的形式。
它其并不是服务器主动发消息到客户端,而是客户端自己不断偷偷请求服务器,只是用户感知而已。
用这种方式的场景也有很多,比较常见的就是扫码登录。
比如某信平台,登录页面二维码出现之后,前端页根本不知道用户扫没扫,于是不断去向后端服务器询问,看有没有人扫过这个码。而且是以大概1到2秒的间隔去不断发出请求,这样可以保证用户在扫码后能在1到2内得到及时的反馈,不至于等太久。
使用HTTP定时轮询
但这样,会有两个比较明显的问题
当你打开F12页面时,你会发现满屏的HTTP请求。虽然很小,但这其也消耗带宽,同时也会增加下游服务器的负担。比较坏情况下,用户在扫码后,需要等个1~2,正好才触发下一次请求,然后才跳转页面,用户会感到明显的卡顿。使用起来的体验就是,二维码出现后,手机扫一扫,然后在手机上点个确认,这时候卡顿等个1~2,页面才跳转。
不断轮询查看是否有扫码
那么问题又来了,有没有更好的解决方案
有,而且现起来成本还非常低。
长轮询
我们知道,HTTP请求发出后,一般会给服务器留一定的时间做响应,比如3,规定时间内没返回,就认为是超时。
如果我们的HTTP请求将超时设置的很大,比如30,在这30内只要服务器收到了扫码请求,就立马返回给客户端页。如果超时,那就立马发起下一次请求。
这样就减少了HTTP请求的个数,并且由于大部分情况下,用户都会在某个30的区间内做扫码操作,所以响应也是及时的。
长轮询
比如,某度云盘就是这么干的。所以你会发现一扫码,手机上点个确认,电脑端页就秒跳转,体验很好。
长轮询的方式来替代
真一举两得。
像这种发起一个请求,在较长时间内等待服务器响应的机制,就是所谓的长训轮机制。我们常用的消息队列RMQ中,消费者去取数据时,也用到了这种方式。
RMQ的消费者通过长轮询获取数据
像这种,在用户不感知的情况下,服务器将数据推送给浏览器的技术,就是所谓的服务器推送技术,它还有个毫不沾边的英文,技术,大家听过就好。
上面提到的两种解决方案,本质上,其还是客户端主动去取数据。
对于像扫码登录这样的简单场景还能用用。
但如果是页游戏呢,游戏一般会有大量的数据需要从服务器主动推送到客户端。
这就得说下了。
是什么
我们知道TCP连接的两端,同一时间里,双方都可以主动向对方发送数据。这就是所谓的全双工。
而现在使用比较广泛的HTTP11,也是基于TCP协议的,同一时间里,客户端和服务器只能有一方主动发数据,这就是所谓的半双工。
也就是说,好好的全双工TCP,被HTTP用成了半双工。
为什么
这是由于HTTP协议设计之初,考虑的是看看页文本的场景,能做到客户端发起请求再由服务器响应,就够了,根本就没考虑页游戏这种,客户端和服务器之间都要互相主动发大量数据的场景。
所以为了更好的支持这样的场景,我们需要另外一个基于TCP的新协议。
于是新的应用层协议就被设计出来了。
大家别被这个字给带偏了。虽然字带了个,但其和之间,就跟雷峰和雷峰塔一样,二者接近毫关系。
在四层络协议中的位置
怎么建立连接我们平时刷页,一般都是在浏览器上刷的,一会刷刷图文,这时候用的是HTTP协议,一会打开页游戏,这时候就得切换成我们新介绍的协议。
为了兼容这些使用场景。浏览器在TCP次握手建立连接之后,都统一使用HTTP协议先进行一次通信。
如果此时是普通的HTTP请求,那后续双方就还是老样子继续用普通HTTP协议进行交互,这点没啥疑问。如果这时候是想建立连接,就会在HTTP请求里带上一些特殊的头。C:UU:S-WS-K:T26ZAQNZ2YU==\\这些头的意思是,浏览器想升级协议(C:U),并且想升级成协议(U:)。
同时带上一段随机生成的64码(S-WS-K),发给服务器。
如果服务器正好支持升级成协议。就会走握手流程,同时根据客户端生成的64码,用某个公开的算法变成另一段字符串,放在HTTP响应的S-WS-A?头里,同时带上101状态码,发回给浏览器。
HTTP11101SP\\S-WS-A:BJKALIW2DA43JHBCY=\\U:\\C:U\\状态码=200(正常响应)的情况,大家见得多了。101确不常见,它其是指协议切换。
64转为新的字符串
之后,浏览器也用同样的公开算法将64码转成另一段字符串,如果这段字符串跟服务器传回来的字符串一致,那验证通过。
对比客户端和服务端生成的字符串
就这样经历了一来一回两次HTTP握手,就建立完成了,后续双方就可以使用的数据格式进行通信了。
建立连接
抓包我们可以用抓个包,际看下数据包的情况。
客户端请求升级为
上面这张图,注意画了红框的第2445?行报文,是的首次握手,意思是发起了一次带有特殊H的HTTP请求。
服务器同意升级为协议
上面这个图里画了红框的4714?行报文,就是服务器在得到首次握手后,响应的第二次握手,可以看到这也是个HTTP类型的报文,返回的状态码是101。同时可以看到返回的报文中也带有各种?相关的信息,比如S-WS-A。
两次HTTP请求之后正式使用通信
上面这张图就是全貌了,从截图上的注释可以看出,和HTTP一样都是基于TCP的协议。经历了次TCP握手之后,利用HTTP协议升级为协议。
你在上可能会看到一种说法:"是基于HTTP的新协议",其这并不对,因为只有在建立连接时才用到了HTTP,升级完成之后就跟HTTP没有任何关系了。
这就好像你喜欢的女生通过你要到了你大学室友的微信,然后他们自己就聊起来了。你能说这个女生是通过你去跟你室友沟通的吗不能。你跟HTTP一样,都只是个工具人。
这就有点"借壳生蛋"的那意思。
HTTP和的关系
的消息格式上面提到在完成协议升级之后,两端就会用的数据格式进行通信。
数据包在中被叫做帧。
我们来看下它的数据格式长什么样子。
报文格式
这里面字段很多,但我们只需要关注下面这几个。
字段:这个是用来标志这是个什么类型的数据帧。比如。
等于1时是指类型()的数据包
等于2是二进制数据类型([])的数据包
等于8是关闭连接的信号
字段:存放的是我们真正想要传输的数据的长度,单位是字节。比如你要发送的数据是字符串"111"?,那它的长度就是3。
另外,可以看到,我们存放长度的字段有好几个,我们既可以用比较前面的7?,也可以用后面的7+16或7+64。
那么问题就来了。
我们知道,在数据层面,大家都是01二进制流。我怎么知道什么情况下应该读7,什么情况下应该读7+16呢
会用比较开始的7做标志位。不管接下来的数据有多大,都先读比较先的7个,根据它的取值决定还要不要再读个16或64。
如果比较开始的7的值是0~125,那么它就表示了全部长度,只读比较开始的7个就完事了。
长度在0到125之间
如果是126(07E)。那它表示的长度范围在126~65535之间,接下来还需要再读16。这16会包含的真长度。
长度在126到65535之间
如果是127(07F)。那它表示的长度范围;=65536,接下来还需要再读64。这64会包含的长度。这能放2的64次方的数据,换算一下好多个TB,肯定够用了。
长度大于等于65536的情况
字段:这里存放的就是真正要传输的数据,在知道了上面的长度后,就可以根据这个值去截取对应的数据。
大家有没有发现一个小细节,的数据格式也是数据头(内含长度)+的形式。
之前写的《既然有HTTP协议,为什么还要有RPC》提到过,TCP协议本身就是全双工,但直接使用纯裸TCP去传输数据,会有粘包的"问题"。为了解决这个问题,上层协议一般会用消息头+消息体的格式去重新包装要发的数据。
而消息头里一般含有消息体的长度,通过这个长度可以去截取真正的消息体。
HTTP协议和大部分RPC协议,以及我们今天介绍的协议,都是这样设计的。
消息边界长度标志
的使用场景完美继承了TCP协议的全双工能力,并且还贴心的提供了解决粘包的方案。它适用于需要服务器和客户端(浏览器)频繁交互的大部分场景。比如页小程序游戏,页聊天室,以及一些类似飞书这样的页协同办公软件。
回到文章开头的问题,在使用协议的页游戏里,怪物移动以及玩家的行为是服务器逻辑产生的,对玩家产生的伤害等数据,都需要由服务器主动发送给客户端,客户端获得数据后展示对应的效果。
的使用场景
总结TCP协议本身是全双工的,但我们比较常用的HTTP11,虽然是基于TCP的协议,但它是半双工的,对于大部分需要服务器主动推送数据到客户端的场景,都不太友好,因此我们需要使用支持全双工的协议。在HTTP11里。只要客户端不问,服务端就不答。基于这样的特点,对于登录页面这样的简单场景,可以使用定时轮询或者长轮询的方式现服务器推送()的效果。对于客户端和服务端之间需要频繁交互的复杂场景,比如页游戏,都可以考虑使用协议。和几乎没有任何关系,只是叫法相似。正因为各个浏览器都支持HTTP协议,所以会先利用HTTP协议加上一些特殊的头进行握手升级操作,升级成功后就跟HTTP没有任何关系了,之后就用的数据格式进行收发数据。? |
|