HTTP vs WebSocket
对于开发者而言,Socket是一套网络编程API,我们利用它可以建立网络连接,比如TCP连接,发UDP数据包
我们平时发的那些请求,比如HTTP、FTP、SMTP,它们底层调用的API就是Socket
拿JAVA来说,我们可以利用一个类,创建一个连接
HTTPURLConnection conn = new xxx;
这个连接的底层肯定是要用Socket API
像这些底层API,操作系统已经准备好了,我们直接调用就可以了
Socket API就是一个方法,一个函数,拿来调就可以了
在JAVA当中它有一个Socket类、ServerSocket类,这些类的底层还是调用的Socket API
我们平时说的Socket,它是一个编程
但是在本篇文章,我们说的WebSocket是一个协议,它跟HTTP有相似点
◼ HTTP请求的特点:通信只能由客户端发起(服务器无法推送消息给客户端)。所以,早期很多网站为了实现推送技术,所用的技术都是轮询
推送技术:客户端没有发消息过去,服务器主动发消息过来
直播消息、聊天网站、股票基金价格是需要实时的,因为这些网站的内容是实时变动的,而这些新的数据是来自服务器,所以服务器要不断的把数据推回给浏览器,就是推送
轮询是指由浏览器每隔一段时间(如每秒)向服务器发出HTTP请求,然后服务器返回最新的数据给客户端
从表面上确实达到了推送的效果,从客户的角度看来,确实是时时更新
有时候一分钟可能要发个三四十个请求,但实际上不是每一次询问,都会有结果
你发询问过去,不一定就有数据给你
每隔一端时间,客户端就会问服务器,有没有东西发给我,即使服务器没有消息也要回它,很浪费资源
为了能更好的节省服务器资源和带宽,并且能够更实时地进行通讯,HTML5规范中出现了WebSocket协议
用在浏览器里面,用在前端里面
WebSocket协议:前两次是在建立WebSocket的连接,客户端发送WebSocket的请求,告诉服务器我需要订阅什么资源,当服务器有的时候,就会推送过来,后面客户端只要乖乖的等服务器推送消息过来,就可以了
WebSocket
◼ WebSocket,是基于TCP的支持全双工通信的应用层协议
在2011年由IETF标准化为RFC 6455,后由RFC 7936补充规范
客户端、服务器,任何一方都可以主动发消息给对方
HTTP不是,他只允许客户端主动发送消息给服务器
◼ WebSocket的应用场景很多
社交订阅、股票基金报价、体育实况更新、多媒体聊天、多玩家游戏等
这个是属于HTML5的范畴
HTTP vs WebSocket
◼ WebSocket和HTTP属于平级关系,都是应用层的协议
其实TCP本身就是支持全双工通信的(客户端、服务器均可主动发消息给对方)
TCP三次握手建立连接,即可开始全双工通信
只是HTTP的“请求-应答模式”限制了TCP的能力
设计之初就定死了,无状态请求,我请求完这个连接,马上就断定了,不会去跟踪状态,用户以前是否登录过,要开发员写代码去跟踪
TCP很强大,但是HTTP只用了TCP的部分功能
WebSocket就是在TCP的基础上做了简单的封装
◼ WebSocket使用80(ws://)、443(wss://)端口,可以绕过大多数防火墙的限制,同时还可以兼容HTTP、HTTPS协议
有些服务器,他就是专门的HTTP服务器,我的防火墙只让80端口的数据过去
HTTPS是用443端口、HTTP是用80端口
协议头:ws
wws加了个TLS/SSL协议,更加安全
ws://example.com/wsapi
ws协议后面不能够写#号
HTTP协议可以对#号进行特殊处理,ws不能
wss://secure.example.com/wsapi
◼ 与HTTP不同的是,WebSocket需要先建立连接
HTTP是在传输层建立连接,然后才开始发数据,在应用层没有
WebSocket是在应用层有建立连接的概念
这就使得WebSocket成为一种有状态的协议,之后通信时可以省略部分状态信息
WebSocket先TCP三次握手建立连接,在应用层再建立一个连接,所以我们互相知道有对方的概念,知道对方在线,以后发数据,直接发过去,而不用每次都告诉对方我是谁,不用做身份验证
而HTTP请求可能需要在每个请求都额外携带状态信息(如身份认证等)
WebSocket更多的是属于应用层的范畴,做前端开发的
WebSocket—建立连接
◼ WebSocket需要借助HTTP协议来建立连接(也叫作握手,
)
WebSocket是HTML5的规范,HTML是用在浏览器里面的,浏览器以前支持HTTP协议,终究是绕不开的,所以WebSocket是借助于HTTP来升级
WebSocket是非常兼容HTTP协议的,相当于是HTTP的升级到WebSocket
由客户端(浏览器)主动发出握手请求
◼ Connection必须设置Upgrade
表示客户端希望连接升级
◼ Upgrade必须设置websocket
表示希望升级到WebSocket协议
这两个头是固定的,如果你想升级到WebSocket协议
◼ Sec-WebSocket-Version
表示支持的Websocket版本
RFC 6455要求使用的版本是13
客户端发一个请求过来,要升级到WebSocket,服务器返回一个响应,说我也想升级
WebSocket—建立连接
◼ Sec-WebSocket-Key是客户端生成的随机字符串,比如例子中的dGhlIHNhbXBsZSBub25jZQ==
◼ 服务器接收到客户端的Sec-WebSocket-Key后,会进行以下操作
① Sec-WebSocket-Key加上一个固定的
值(258EAFA5-E914-47DA-95CA-C5AB0DC85B11)
dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11
② 将①的结果进行SHA-1摘要计算(单项散列函数)
b37a4f2cc0624f1690f64606cf385945b2bec4ea
加密地址:在线加密解密 - chahuo.com
③ 将②的结果进行Hex To Base64编码
s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
加密地址:Hex to Base64 | Base64 Encode | Base64 Converter | Base64
Base64编码是单个字符加密
Hex To Base64编码是把加密前字符串当作16进制数值进行编码,两个字符加密
所以不一样
④ 将③的结果做为Sec-WebSocket-Accept响应头的值,返回给客户端
◼ 如此操作,可以尽量避免普通HTTP请求被误认为WebSocket协议
仅靠Connection、Upgrade两个头,就判断要升级为WebSocket太草率了,如果有人只是想试一下,没想到就升上去了,但是客户端又不用,后面就会不知道该如何处理,会浪费资源,所以客户端要给服务器点诚意,发一串随机值,服务器加密一下,发给客户端解密,解出来,是对的,说明服务器那边也想建立连接,我们就升级成功
WebSocket—使用
◼ WebSocket体验和演示
https://www.websocket.org/echo.html
◼ W3C标准化了一套WebSocket API,可以直接使用JS调用
如何过滤查看ws的数据
Network>ws>Messages
建立好连接之后,我们之间就可以开始双向通信了,不像HTTP一来一回都是一个请求
WebSocket协议其实还是个HTTP请求,只不过我请求的URL是WSS
101,相当于同意WebSocket建立连接
WebService
◼ WebService,译为:Web服务,是一种跨编程语言和跨操作系统平台的远程调用技术标准
客户端开发了一套APP,针对不同的平台,我们开发的APP编程语言是不一样的,比如安卓的是用JAVA\Kotlin、IOS用的是OC\Swift,不管我们用的是什么语言,我们都可以去调用服务器公开的数据。服务器可能是用JAVA写的、也有可能是用PHP写的,操作系统可能是Linux或者Windows,没关系,我都可以返回数据给你,这就是跨编程语言和跨操作系统平台
没有WebService,在我们以前的认知里面,数据调用本来就是跨编程语言和跨操作系统平台的
只要服务器是一台HTTP服务器,它部署的是什么编程语言的代码或者什么操作系统,都没有什么关系,都可以返回数据给我的客户端
◼ WebService使用场景举例
天气预报、手机归属地查询、航班信息查询、物流信息查询等
WebService的开放是完全免费的,服务器上的数据是完全公开的,不是我们印象当中的开放平台
比如天气预报,是气象局把自己的服务以WebService形式暴露出来,让第三方程序可以调用这些服务功能
天气预报:气象局用卫星或者各种方式获取天气情况,在把天气数据公开,如果有人想要直接拿就好了
手机归属地查询:输入你的手机号,我能知道你是那个营业厅的
物流信息查询:通过不同的软件,比如淘宝、京东,你可以看到自己商品的物流信息,而这些商品有可能走的是申通或者韵达,但是我们却可以看见,那是因为这些数据来自物流公司,也就是说淘宝、京东这些APP调用了申通、韵达的物流信息,那就说明这些物流公司,是把自己的物流信息开放出来,等着别人去调
http://www.webxml.com.cn/zh_cn/index.aspx
我们看到的是一个简简单单的http请求,图例展示的严格来讲,不算WebService,它只是返回了一个XML文档
现在公司都是统一返回JSON
广义上来说,我有台服务器提供了很多的接口给你调用,那我这些接口返回的数据,不都是WEB服务,通过WEB的方式获取到服务
◼ 事实上,WebService完全可以用普通的Web API取代(比如HTTP + JSON)
现在很多人都是用JSON\PROTOBUF,但是用JSON的还是更多点
我发送一个http请求过去,服务器返回一个JSON
以前比较旧的一套标准,现在很多公司都不用它了,因为太麻烦了,发东西还要用XML文档,现在谁还用XML文档
WebService标准的请求和响应模式:http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?op=getRegionCountry
是需要写代码去搞的,如果我们遇到平台有用这个协议,那我们就按它的格式发过去
我们现在的请求—应答模式就是跨编程语言和跨操作系统平台的远程调用技术
现在很多企业的开放平台都是直接采用Web API
我告诉你URL,该发什么参数,你直接返回给我就好了
开放平台,微博有很多种客户端,为什么有这么多的客户端,因为微博开放了平台的接口,微博有很多服务器开放了API给我们调用,比如我去开发一个我自己的客户端,我就可以去调用微博的数据,发请求给微博服务器,服务器就会返回数据给我
利用QQ登录京东,这就是第三方登录,多多少少要QQ的服务器开放API接口,我们才可以实现这样的技术
你要注册成为平台的开发者,你才可以调用开放平台的数据
这个时候平台就会给我们key,根据这个key,平台就会知道,你是一个合法的开发者,在我这边是注册过的
开发者每一次请求数据,都会带上key,开放平台根据这个key,会知道你这个请求,是来自那一个开发者
这个key是用在我们开发的应用里面,比如开发者开发一个新的应用,平台就会给一个新的key,key用在应用里面,这样应用请求的时候,平台就会知道是那个应用在请求
好统计谁在用我的key,用得怎么样
有些开发平台,key是要收费的,一个小时里面只能请求50次,超过50次要收费,如果你想没有限制,那就要交钱,按月交,按年交,靠公司的数据开放出去挣钱
现在很多公司用的SDK,都是按照这个模式来收费(SDK:软件开发工具包)
WebService—核心概念
◼ SOAP(Simple Object Access Protocol),译为:简单对象访问协议
把简称看成一个单词,就是肥皂,所以我们又叫它肥皂协议
很多时候,SOAP = HTTP + XML
XML的格式跟HTML很像
WebService使用SOAP协议来封装传递数据
双方之间都是通过SOAP协议,来传递数据
还是发送HTTP请求,还是给回我HTTP响应,只不过我们发的请求和响应都是XML文档,也就是双方之间都是用XML来通信,比如说,我发一个请求过去,我的请求体就是一个XML文档,响应也是这样子,这个就叫SOAP协议
SOAP协议有规定XML文档该怎么写
怎么写标签,标签是用来干什么用的,都规定好了
规定好发送格式,必须是XML,XML里面用什么格式
◼ WSDL(Web Services Description Language),译为:Web服务描述语言
一个XML文档,用以描述WebService接口的细节(比如参数、返回值等)
我想知道你这个服务器提供了那些服务,那些开放数据给我,这个时候,我们只要看一下WSDL,我就知道你提供了哪些接口给我,我可以访问哪些数据
一般在WebService的URL后面跟上?wsdl获取WSDL信息
✓ 比如:http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl
WebService的说明书,说明一下提供了哪些接口/功能给我用
有些平台,它想将自己的数据公布出来,给别人使用,没有限制的那种,这个时候大家就要遵循一个标准,这个标准就叫WebService标准
标准规定了,你们以后想开放一个数据给别人使用,那就需要遵守一个SOAP协议,这个协议规定了你的请求和响应的文档应该怎么写,如果你想看它提供了那些接口,你可以访问一下?wsdl。
如果以后公司采用WebService标准,那我就知道要发什么请求给它,以后发SOAP请求给它,它就会返回数据给我
WebService是一个服务开放标准,我想开放数据给你用,大家就统一使用WebService标准
RESTful—简介
◼ REST的全称是:REpresentational State Transfer
译为“表现层状态转移”
◼ REST是一种互联网软件架构设计风格
不是一个标准和规范,我们可以不去遵守,一种理念
编码风格,那种都可以,是一个个人爱好
定义了一组用于创建Web服务的约束
对我们的请求进行了约束
符合REST架构的web服务,称为RESTful Web服务
开发的风格是REST的,我们就叫RESTfulAPI
RESTful—实践建议
◼ URL中使用名词(建议用复数形式),不使用动词
update是动词,很明显不符合RESTful的风格
推荐: /users、 /users/6
不推荐:/listUsers 、 /getUser?id=6、 /user/list、 /user/get?id=6
list:列出
get:拿到
都是动词,不推荐
RESTful不是强制的,只是建议你遵守这个标准
那我怎么表达动作
◼ 使用HTTP的方法表达动作
还有HEAD/OPTIONS请求,但是这里只用四种
根据请求的方法不同,URL会把它理解为不同的操作
POST是用来添加的,你给我一个6,我不知道你想干吗,用来添加id为6的用户吗,不可能。
一般公司后台想要添加用户,是要给服务器用户的信息,id是由服务器自动生成的,不是你客户端告诉我你用户什么id,所以方法不被允许
URL很简洁,只是通过不同的请求方法,确定不同的动作,这种方法是比较优雅的
◼ 一个资源连接到其他资源,使用子资源的形式
GET /uesrs/6/cars/88
查询id为6的用户名下的88号车
POST /users/8/cars
给ID为8的用户创建一辆车
RESTful—实践建议
◼API版本化
mj.com/v1/users
mi.com/v2/users/66
不同的版本返回的消息不一样
◼ RESTfulAPI返回JSON格式的数据
◼ 发生错误时,不要返回200状态码
发生错误时,状态码改为400
成功返回信息,状态码默认200,这个在RESTful里面,就存在误导,如果发生错误,那就给回他一个错误的状态码
RESTful一开始感觉很奇怪,用多了就熟悉了
HTTPDNS
◼ HTTPDNS是基于HTTP协议向DNS服务器发送域名解析请求
以前的DNS服务器是由IPS提供的,没有指定的话,走的就是运营商的DNS服务器
直接发送HTTP请求给DNS服务器,我们的这台DNS服务器相当于HTTP服务器,只不过它的功能跟DNS服务器是一样的,告诉我们域名对应的IP是什么,但本质其实是一台HTTP服务器,返回HTTP响应给我们,这就是我们为什么可以向DNS服务器发送HTTP请求,因为它就是一台HTTP服务器,只是功能相当于DNS服务器
替代了基于DNS协议向运营商Local DNS发起解析请求的传统方式
可以避免Local DNS造成的域名劫持和跨网访问问题
因为有人喜欢去攻击运营商的DNS服务器,就会导致各种各样的问题
常用在移动互联网中(比如在Android、iOS开发中)
浏览器内部走的是操作系统配置的DNS,没配置肯定走运营商的
移动的应用端代码是我写的,我就可以修改走那个DNS服务器
有的公司会要求走HTTPDNS服务器
云平台,提供了HTTPDNS的功能,公司发请求到HTTPDNS服务器,就会告诉我们IP地址
看一下就好,没有上面写的这么厉害,不过跟IPS比肯定是有优势的,不过要交钱
HTTPDNS—使用
◼ 市面上已经有现成的解决方案
腾讯云:https://cloud.tencent.com/product/httpdns
主要是移动端应用
阿里云:https://help.aliyun.com/product/30100.html
◼ 移动端集成相关的SDK即可使用HTTPDNS服务
开发一个桌面应用,Windows平台的桌面,我这个桌面想要进行DNS解析,那我可以集成SDK,现在有些公司就有桌面版的SDK
腾讯云:客户支持>SDK中心>移动解析HttpDNS
去官网下载,嵌入到SDK内部,就会发请求到腾讯云的HTTPDNS,然后解析出IP地址给我们
FTP
做邮件调用一下SDK、API就好了
◼ FTP(File Transport Protocol),译为:文件传输协议,RFC 959定义了此规范,是基于TCP的应用层协议
专门用于传输文件,FTP服务器上面有文件,客户端通过连接到FTP服务器,上传和下载文件
HTTP服务器也可以下载资源,为什么不用它
HTTP服务器设计之初是用来传输网页的,简单的文本信息,下载大文件或者做文件传输,这并不是HTTP服务器的优势,针对文件上传和下载有专门的协议,那就是FTP协议,专门的事就应该交给专门的人做
FTP协议针对文件上传和下载做过专门的优化
在RFC 1738中有定义,FTP的URL格式为:ftp://[user[:password]@]host[:port]/url-path
跟我们以前学的HTTP格式有点像,可以在URL当中输入账号和密码
FTP服务器,要有用户名和密码才可以登录,不是谁都可以下载服务器的文件,请求的时候要告诉FTP服务器用户名和密码
登录成功,甚至可以把FTP服务器的文件给删掉
在网上找些软件集,就可以开始搭建服务器和客户端了,进行上传和下载
FTP—连接模式
◼ FTP有2种连接模式:主动(Active)和被动(Passive)
◼ 不管是哪种模式,都需要客户端和服务器建立2个连接
① 控制连接:用于传输状态信息(命令,cmd)
告诉服务器你要干什么,告诉客户端你要干什么
② 数据连接:用于传输文件和目录信息(data)
文件数据和想看文件夹里面有多少东西
FTP—主动模式
① 客户端打开一个随机的命令端口
端口号大于1024,假设为N
这个端口将来用作控制连接,也就是用来传输命令的
同时连接至服务器的命令端口21
这个端口是固定死的
② 客户端开始监听N+1数据端口
打开一个新的端口,N+1号端口
同时向服务器发送一个Port命令给服务器的命令端口21
告诉服务器我的数据端口
此命令告诉服务器
✓ 客户端正在监听的数据端口N+1
就是用这个端口来进行监听的
✓ 并且已准备好从此端口接收数据
③ 服务器打开20号数据端口,并且创建和客户端数据端口(N+1)的连接
这个端口也是固定的
感觉是服务器在主动
FTP—被动模式
◼ 客户端通过两个随机的端口与服务器建立连接
命令端口N
数据端口N+1
① 客户端的命令端口N用于连接服务器的命令端口21
② 客户端通过命令端口N发送PASV命令给服务器的命令端口21
告诉服务器要开启被动模式
③ 服务器打开一个随机的数据端口P,并告知客户端该端口号P,用我这个端口号
服务器开启被动模式,打开一个随机端口,这次就不用20了,空着
④ 客户端数据端口N+1发起与服务器数据端口P的连接
打开一个新的端口,N+1号端口
邮件相关的协议
浅层邮件开发,调一下API,收发邮件调一下方法,收邮件的时候在解析一下
◼ 发邮件使用的协议
SMTP(Simple Mail Transfer Protocol),译为:简单邮件传输协议
✓ 基于TCP,标准参考RFC 5321
保证邮件完整
✓ 服务器默认使用25端口,SSL/TLS使用465端口
加密了话,就是465端口
◼ 收邮件使用的协议
POP(Post Office Protocol),译为:邮局协议
✓ 基于TCP,最新版是POP3,标准参考RFC 1939
✓ 服务器默认使用110端口,SSL/TLS使用995端口
IMAP(Internet Message Access Protocol),译为:因特网信息访问协议
✓ 基于TCP,最新版是IMAP4,标准参考RFC 3501
✓ 服务器默认使用143端口,SSL/TLS使用993端口
收邮件的协议,两个当中选一个
收发邮件的过程
邮件发送肯定要经过服务器的中转,没办法直接发过去
QQ邮箱用户走SMTP协议发送邮件给QQ邮箱服务器,QQ邮箱服务器在走SMTP协议中间经过internet,到达新浪邮箱服务器,这边新浪邮箱服务器就会收到QQ邮箱用户发送过来的邮件
只要是发邮件就是SMTP
一打开QQ邮箱就会去拉取QQ邮箱服务器的邮件,通过POP/IMAP下载到我的本地
POP vs IMAP
◼ POP的特点
客户端连接服务器时,将会从服务器下载所有邮件
整个邮件副本拷贝下来
✓ 可以设置下载完后,立即或一段时间后删除服务器邮件
客户端的操作(比如删除邮件、移动到文件夹)不会跟服务器同步
它们的连接是单向的
每个客户端都是独立的,都可以获得其自己的电子邮件副本
用同一个账号在不同的设备登录,设备之间的操作是完全独立的
◼ IMAP的特点
连接是双向的
客户端连接服务器时,获取的是服务器上邮件的基本信息,并不会下载邮件
邮件的列表信息,你有多少封未读邮件、是谁发的,大概内容是什么等一些摘要信息
✓ 等打开邮件时,才开始下载邮件
客户端的操作(比如删除邮件、移动到文件夹)会跟服务器同步
要不要同步,开发客户端的人可以去限制,比如用户在删除邮件的时候,询问他是否连服务器的一起删除,如果选择不是,那就删除本地缓存
IMAP提供了一个功能,允许我们去删除服务器的邮件,但是要不要删,取决于我们
所有客户端始终会看到相同的邮件和相同的文件夹
同一个账号在不同的设备登录,所看到的文件是一样的,一边做了改动,就会同步到另一边
用那个协议是根据公司的情况来