http请求方式
在web引用中,http通信主要是通过请求-应答的方式,即客户端发出请求,浏览器做出应答。
比如说我们浏览百度,当我们输入网址并回车,客户端就向服务器发起请求。我们看到的内容就是服务器做出的相应应答。
问题背景
在进行扫码登录时,如何判断用户扫码并登录了?
方法1:轮询
只要客户端定期请求服务器,拉取扫码登录结果即可。
那么问题来了,到底轮询的频率是多少呢?轮询频率过高会给服务器造成压力,轮询频率过低会让用户感觉扫码登录响应过慢。
方法2:长轮询
在轮询的基础上,服务器收到请求消息后,保持连接直到返回扫码登录成功的结果。
使用长轮询,返回消息时序性无法保证;同时,不管是轮询还是长轮询,都逃不开请求-响应的模式。
比如说,扫码登录会返回两个结果:扫码成功通知和确认登录通知。
但是由于长轮询不保证时序性,客户端先收到确认登录通知,后收到扫码成功通知。
所以,对时序性有要求的web服务,如果不能保证时序性,最好不要使用轮询方法。
方法3:websocket
如何让服务器主动推送消息呢?如何保证接受消息的时序性呢?可以使用websocket实现。
websocket
websocket是基于tcp的一种全双工应用层通信协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,WebSocketAPI被W3C定为标准。
因为是基于tcp的通信协议,故只需一次请求响应操作即可建立连接。
websocket握手过程
通常是在http通信中请求转换到websocket协议。这里以聊天室为例,讲http创建过程。
如果没有了解http,建议先了解http再看本文后面的内容,传送门:小林coding-HTTP基本概念
客户端请求
客户端首先发起一次http请求,格式如下:
必要字段解析:
字段 | 解释 |
---|---|
请求方法和HTTP版本 | 请求方法必须为GET,http版本必须为HTTP1.1及以上 |
Status Code:101 | 状态码101 表示协议转换,这里指将协议转换到websocket |
Upgrade: websocket | 必要字段,表示通信协议更新到websocket |
Sec-WebSocket-Key | 为一串16字节随机字符串base64加密后的值 |
Sec-WebSocket-Version: 13 | 必须为13 |
服务端响应
必要字段解析:
字段 | 解释 |
---|---|
Connection: Upgrade | 必须为Upgrade |
Sec-WebSocket-Accept | 根据客户端传入的Sec-WebSocket-Key的值,计算获得结果 |
Sec-WebSocket-Version: 13 | 必须为13 |
Upgrade: websocket | 必要字段,表示通信协议更新到websocket |
Sec-WebSocket-Accept计算过程
拿到Sec-WebSocket-Key的值后,在后面加入字符串258EAFA5-E914-47DA-95CA-C5AB0DC85B11
得到新的字符串,再将该字符串进行sha-1编码,最后进行base64编码,即Sec-WebSocket-Accept的值。
计算过程php代码实例
<?php
$input = readline(input:);
echo base64_encode(sha1($input . 258EAFA5-E914-47DA-95CA-C5AB0DC85B11, true));
验证结果:
计算结果和Sec-WebSocket-Accept的值一致。
客户端最后操作
客户端收到应答后,要校验Sec-WebSocket-Key的值,如果该值和计算结果不符,或者不符合上面过程任一要求,则拒绝创建websocket连接。
如果客户端校验无误,websocket就握手完成了。
既然有TCP了,为什么还要用websocket呢?
背过八股文学过计网的同学都知道,tcp是面向连接的、可靠的、基于字节流的传输层协议,同时tcp也是一个全双工通信协议。那么有了tcp,为什么还要用websocket呢?
个人理解是:tcp是传输层协议,而websocket是应用层协议。tcp只保证报文传输的可靠性、全双工等特性,但tcp是基于字节流形式,如何解决沾包问题交给了应用层,其次,业务相关的其他需求也应该由应用层解决。
还没发表评论,快来发表第一个评论吧~