原文: 蜀道如天夜雨淫,乱铃声里倍沾襟。
当时更有军中死,自是君王不动心。
译文及注释:
蜀道:指川西地区的道路。
如天:像天空一样广阔。
夜雨淫:夜间雨水连绵不断。
乱铃声里倍沾襟:在淅淅沥沥的雨声中,铃声不停地响起,使人倍感凄凉。
当时更有军中死:当时还有许多士兵在战争中死去。
自是君王不动心:这些死亡并没有让君王感到悲痛。
注释:
蜀道:指川西地区的道路,因为地势险峻而著名。
夜雨淫:指夜间大雨倾盆。
乱铃声:指战争中的警报铃声。
倍沾襟:形容雨水很大,衣服被淋湿。
军中死:指在战争中死亡的士兵。
君王不动心:指当时的统治者对士兵的死亡漠不关心。
译文及注释详情»
鉴赏:
李靓的这首绝句《鸣雁》是一篇读后感兼咏史诗。相较于前人的创作,李靓的立意更为新颖和高雅。在前两句中,李靓引用了《长恨歌》中李隆基夜雨闻铃的描写,进而描写了唐朝战争的惨状。诗人在后两句中使用春秋笔法进行警策,强调了官军的惨状。与前人写女性祸水的错误观念不同,李靓关注的是战争带来的苦难和灾难。整首诗凝聚了作者对战争悲惨的看法,强调了和平和安定的珍贵,并且对读者提出呼吁。
总之,从创作角度来看,这首绝句充满了创见和新意,特别是李靓对历史事件的深入思考,更是展现出了其深厚的文学功底和扎实的历史素养。这首诗既是一篇优秀的文学作品,也是一篇生动的历史记述,具有很高的艺术价值和历史价值。
鉴赏详情»
译文及注释:
到蜀地的道路比上青天还难,何况是在夜间,又不断地下起了雨呢!值此时刻,唐玄宗想起了杨贵妃,眼泪就伴着铃声不断地流下来了。
【注释】:
1. 蜀地:指中国古代的蜀地,位于现今的四川省。
2. 上青天:指极为险峻的山峰。这里用来形容到蜀地的路非常艰难。
3. 杨贵妃:唐代著名美女,唐玄宗的宠妃。她的悲剧性命运与唐玄宗密不可分。
4. 铃声:指宫廷中的铃声,是唐玄宗听见的声音。
译文及注释详情»
李觏简介: 1.HTTP状态码
1xx 信息性状态码 websocket upgrade 表示接收到请求并且正在处理
100 Continue:表示客户端应该继续发送请求。
101 Switching Protocols:表示服务器已经理解了客户端的请求,并将通过Upgrade 消息头通知客户端采用不同的协议来完成这个请求。
102 Processing:表示服务器已经接收到并正在处理请求,但是响应还没有完成。
2xx 成功状态码
200 OK:表示请求已成功。
204 No Content:表示服务器已经成功处理了请求,但是没有返回任何内容。该状态码常用于更新操作,表示更新已经成功完成,但是不需要返回响应内容。
206 Partial Content:表示服务器已经成功处理了部分 GET 请求,并返回了请求范围内的实体内容。该状态码通常用于支持断点续传和大文件下载等场景。
3xx 重定向状态码
301 Moved Permanently:永久重定向。表示请求的资源已经永久移动到了一个新的 URI,客户端应该使用新的 URI 进行请求。浏览器会自动重定向到新的 URI,搜索引擎会更新索引。
302 Found:临时重定向。表示请求的资源暂时移动到了一个新的 URI,客户端应该使用新的 URI 进行请求。浏览器会自动重定向到新的 URI,搜索引擎不会更新索引。
303 See Other:表示请求的资源可以在另一个 URI 中找到,并且客户端应该使用 GET 方法进行请求。该状态码常用于 POST 请求的重定向,避免客户端无意中再次提交表单数据。浏览器会自动重定向到新的 URI,搜索引擎会更新索引。
304 Not Modified:表示客户端请求的资源在服务器上没有发生变化,可以直接使用客户端缓存的版本。服务器会返回一个空的响应体,告诉客户端直接使用缓存。该状态码一般在客户端发送条件 GET 请求时使用。
307 Temporary Redirect:临时重定向。和 302 Found 类似,表示请求的资源暂时移动到了一个新的 URI,客户端应该使用新的 URI 进行请求。和 302 Found 不同的是,307 Temporary Redirect 要求客户端保持请求方法不变进行重定向,比如如果客户端使用 POST 请求,那么重定向后的请求也应该使用 POST 方法。浏览器会自动重定向到新的 URI,搜索引擎不会更新索引。
4xx 客户端错误状态码
400 客户端参数错误
401 没有登录
403 登录了没权限 比如管理系统
404 页面不存在
405 禁用请求中指定的方法
5xx 服务端错误状态码
500 服务器错误:服务器内部错误,无法完成请求
502 错误网关:服务器作为网关或代理出现错误
503 服务不可用:服务器目前无法使用
504 网关超时:网关或代理服务器,未及时获取请求
2.HTTP分层
七层模型是一种通信协议的分层模型,也称为OSI参考模型
应用层(Application Layer):这个层次提供了用户接口和网络服务之间的接口。它包括网络应用程序和应用程序的协议,如HTTP、FTP、SMTP、DNS等。
表示层(Presentation Layer):这个层次提供了数据格式化和代码转换,确保应用程序所发送的数据可以被接收方理解。它包括加密、压缩和转换数据格式的协议,如JPEG、MPEG、TLS等。
会话层(Session Layer):这个层次负责管理应用程序之间的会话。它包括建立、维护和结束会话的协议,如RPC、NetBIOS等。
传输层(Transport Layer):这个层次提供端到端的可靠传输,包括错误检测和恢复、流量控制和拥塞控制等协议,如TCP、UDP等。
网络层(Network Layer):这个层次负责网络间的数据传输,包括路由选择和流量控制等协议,如IP、ICMP等。
数据链路层(Data Link Layer):这个层次提供了相邻节点之间的可靠传输,包括数据帧的封装和错误检测等协议,如以太网、WiFi等。
物理层(Physical Layer):这个层次负责传输介质和信号的物理特性,如光纤、电缆、无线电波等。
3.HTTP报文是什么样子的
HTTP 请求报文通常包含以下部分:
请求行:包含请求方法、请求 URI 和 HTTP 版本信息。
头部字段:包含了请求的各种附加信息,例如请求头、Cookie、认证信息等。
空行:用于分隔头部字段和请求体。
请求体:可选的请求正文,通常用于 POST 和 PUT 方法中,用于提交表单数据或上传文件等。
HTTP 响应报文通常包含以下部分:
状态行:包含响应状态码、响应短语和 HTTP 版本信息。
头部字段:包含了响应的各种附加信息,例如响应头、Cookie、认证信息等。
空行:用于分隔头部字段和响应体。
响应体:包含服务器返回的数据,通常用于返回 HTML、JSON、XML 或图片等资源。
在这里插入图片描述
4.HTTP之URL
是用来唯一标记服务器上资源的一个字符串,通常也称为 URL;
URI 通常由 scheme、host:port、path 和 query 四个部分组成,有的可以省略;
scheme 叫“方案名”或者“协议名”,表示资源应该使用哪种协议来访问; “host:port”表示资源所在的主机名和端口号;
path 标记资源所在的位置;
query 表示对资源附加的额外要求;
在 URI 里对“@&/”等特殊字符和汉字必须要做编码,否则服务器收到 HTTP报文后会无法正确处理
5.HTTP实体数据
1.数据类型与编码
HTTP 实体数据的数据类型由 MIME type 表示,例如 text/plain、application/json、image/png 等。而 HTTP 实体数据的编码类型则由 Content-Encoding 表示,例如 gzip、deflate 等。在 HTTP 报文头中,可以使用Content-Type字段表示数据类型,使用Content-Encoding字段表示编码类型。
2.数据类型使用的头字段
HTTP 协议为此定义了两个Accept请求头字段和两个Content实体头字段,用于客户端和服务器进行“内容协商”。也就是说,客户端用 Accept 头告诉服务器希望接收什么样的数据,而服务器用 Content 头告诉客户端实际发送了什么样的数据。
在这里插入图片描述
3.语言类型使用的头字段
在这里插入图片描述4.内容协商的质量值
在 HTTP 协议里用 Accept、Accept-Encoding、Accept-Language 等请求头字段进行内容协商的时候,还可以用一种特殊的“q”参数表示权重来设定优先级,这里的“q”是“quality factor”的意思。
Accept: text/html,application/xml;q=0.9,*/*;q=0.8
它表示浏览器最希望使用的是 HTML 文件,权重是 1,其次是 XML 文件,权重是 0.9,最后是任意数据类型,权重是0.8。服务器收到请求头后,就会计算权重,再根据自己的实际情况优先输出 HTML 或者 XML。
5.内容协商的结果
Vary: Accept-Encoding,User-Agent,Accept
这个结果表示服务器在进行内容协商时,考虑了 Accept-Encoding、User-Agent 和 Accept 这三个请求头字段的值。而 Vary 响应头字段则表明了响应内容的不同版本是由于请求头中的哪些字段产生的变化而产生的。具体来说:
Accept-Encoding:表示响应内容是否被压缩过;
User-Agent:表示响应内容是否适用于特定的浏览器或操作系统;
Accept:表示响应内容的格式或类型是否适合客户端的要求。
因此,当客户端发起请求时,如果请求头中的这三个字段的值发生了变化,服务器可能会返回不同版本的响应内容。而通过设置 Vary 响应头字段,服务器可以告知客户端对于这些字段的变化,应该如何处理缓存。
总结:
数据类型表示实体数据的内容是什么,使用的是MIME type,相关的头字段是 Accept和 Content-Type;
数据编码表示实体数据的压缩方式,相关的头字段是Accept-Encoding 和 Content-Encoding;
语言类型表示实体数据的自然语言,相关的头字段是Accept-Language 和 Content-Language;
字符集表示实体数据的编码方式,相关的头字段是Accept-Charset和 Content-Type;
客户端需要在请求头里使用 Accept 等头字段与服务器进行“内容协商”,要求服务器返回最合适的数据; Accept 等头字段可以用“,”顺序列出多个可能的选项,还可以用“;q=”参数来精确指定权重。
6.谈一谈HTTP协议优缺点
超文本传输协议,HTTP AUfXpKH3HhwRznxTSrWvMJTaAXhT7W3s5i1fgxC5vaES
HTTP 特点
灵活可扩展。一个是语法上只规定了基本格式,空格分隔单词,换行分隔字段等。另外一个就是传输形式上不仅可以传输文本,还可以传输图片,视频等任意数据。
请求-应答模式,通常而言,就是一方发送消息,另外一方要接受消息,或者是做出响应等。
可靠传输,HTTP是基于TCP/IP,因此把这一特性继承了下来。
无状态,无状态也会减少网络开销,比如类似直播行业这样子等,这个分场景回答即可。
HTTP 缺点
无状态,有时候,需要保存信息,比如像购物系统,需要保留下顾客信息等等,这个还是分场景来说。
**明文传输,**即协议里的报文(主要指的是头部)不使用二进制数据,而是文本形式。这让HTTP的报文信息暴露给了外界,给攻击者带来了便利。
队头阻塞,因为在 HTTP/1.1 中,同一个 TCP 连接只能有一个请求或响应被处理,即每次只能传输一个请求或响应,而在处理一个请求时,如果前面的响应未完成,后续的请求就必须等待前面的响应完成后才能处理,这就导致了 HTTP 队头阻塞。
为了解决 HTTP 队头阻塞问题,HTTP/2 引入了多路复用(Multiplexing)技术,可以在同一个 TCP 连接中同时处理多个请求和响应,提高了网络性能和响应速度。
7.http无连接怎么理解
HTTP 的无连接特性是指,每次客户端与服务器之间进行一次请求和响应的交互后,连接就会立即关闭,而且客户端与服务器之间并没有保持连接的状态。这意味着,当客户端需要与服务器进行下一次交互时,需要重新建立连接,发送请求并等待响应,然后再关闭连接。
这种设计的好处是可以避免服务器在维护大量连接时产生的开销和复杂性,同时也能够在请求结束后及时释放资源,保持服务器的高效性能。但是,也会造成在处理大量请求时频繁地建立和关闭连接,从而增加网络通信的开销。因此,在实际应用中需要权衡利弊,根据实际情况来选择适当的连接方式。
8.http协议无状态中的 状态 到底指的是什么?!
在HTTP协议中,所谓的“无状态”(stateless)指的是每个请求都是独立的、不依赖于之前或之后的请求。也就是说,服务器在处理每个请求时并不知道这个请求与之前或之后的请求是否有关联,不会记住这些请求的信息或状态。
“状态”指的是请求之间的上下文信息或数据。
例如,用户登录系统后,服务器会在一定时间内记录用户的登录状态,使得在此期间内的请求都能够自动登录。这种状态是建立在请求之间的上下文中,需要服务器在请求之间进行维护。
HTTP协议是无状态的,因为它不会在请求之间保留上下文信息,每个请求都是独立的。这种设计的好处是可以提高服务器的可伸缩性和性能,但也会增加一些额外的开发和维护工作。
9.说一说HTTP 的请求方法
HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法
HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT
http/1.1规定了以下请求方法(注意,都是大写):
GET: 请求获取Request-URI所标识的资源
POST: 在Request-URI所标识的资源后附加新的数据
HEAD: 请求获取由Request-URI所标识的资源的响应消息报头
PUT: 请求服务器存储一个资源,并用Request-URI作为其标识(修改数据)
DELETE: 请求服务器删除对应所标识的资源
TRACE: 请求服务器回送收到的请求信息,主要用于测试或诊断
CONNECT: 建立连接隧道,用于代理服务器
OPTIONS: 列出可对资源实行的请求方法,用来跨域请求
HTTP的OPTIONS方法是一种用于在客户端和服务器之间协商可以使用的请求方法的机制。当客户端发送OPTIONS请求时,服务器会返回一个包含可用请求方法列表的响应。这样,客户端就可以在不进行实际请求的情况下了解服务器可以接受哪些请求方法。
CONNECT方法是HTTP/1.1协议中定义的一种用于建立隧道代理连接的方法,它可以在代理服务器和目标服务器之间建立一条连接隧道,以便在客户端和服务器之间进行端对端的数据通信。这种方法通常用于SSL/TLS加密的HTTPS请求。通过建立连接隧道,代理服务器可以将加密的HTTPS请求传递给目标服务器,并将服务器的响应传递回客户端,而无需对加密数据进行解密和加密操作。
10.谈一谈GET 和 POST 的区别
本质上,只是语义上的区别,GET 用于获取资源,POST 用于提交资源。
具体差别??
从缓存角度看,GET 请求后浏览器会主动缓存,POST 默认情况下不能。
从参数角度来看,GET请求一般放在URL中,因此不安全,POST请求放在请求体中,相对而言较为安全,但是在抓包的情况下都是一样的。
从编码角度看,GET请求只能经行URL编码,只能接受ASCII码,而POST支持更多的编码类型且不对数据类型限值。
GET请求幂等,POST请求不幂等,幂等指发送 M 和 N 次请求(两者不相同且都大于1),服务器上资源的状态一致。
GET请求会一次性发送请求报文,POST请求通常分为两个TCP数据包,首先发 header 部分,如果服务器响应 100(continue), 然后发 body 部分。
在HTTP中,幂等指同一个请求被执行多次,每次执行的结果都是一致的,不会因为执行多次而产生副作用或不同的结果。
幂等性对于一些对数据一致性要求比较高的操作非常重要,例如查询、获取资源等操作。
对于GET请求,由于它不会对资源进行修改,因此它具有幂等性。因为每次请求只是获取资源的操作,不会对资源产生任何副作用。
而POST请求,由于它可能会对资源进行修改或者创建新的资源,因此它一般不具有幂等性。如果同一个请求被执行多次,那么每次执行的结果可能都不同,例如每次都会创建一个新的资源。
需要注意的是,虽然GET请求本身是幂等的,但是如果在请求URL中携带了不同的参数,那么可能会得到不同的结果。因此,需要保证相同的参数产生相同的结果,才能保证请求的幂等性。
11.谈一谈队头阻塞问题
什么是队头阻塞?
对于每一个HTTP请求而言,这些任务是会被放入一个任务队列中串行执行的,一旦队首任务请求太慢时,就会阻塞后面的请求处理,这就是HTTP队头阻塞问题。
并发连接
我们知道对于一个域名而言,是允许分配多个长连接的,HTTP 协议允许一个域名分配多个长连接,也就是说客户端可以与同一个服务器建立多个连接来并发传输请求和响应,从而提高数据传输的效率。
举个例子,Chrome中是6个。
域名分片
我们可以在一个域名下分出多个二级域名出来,而它们最终指向的还是同一个服务器。
例如,对于一个名为example.com的网站,可以使用如下二级域名分片:
www.example.com
images.example.com
api.example.com
cdn.example.com
这些二级域名指向同一个服务器,但是它们各自有自己的 IP 地址,这样在客户端发起请求时,可以根据域名将请求分发到不同的任务队列中进行处理,从而提高了并发能力。同时,这种方式也可以减轻队头阻塞的问题,因为每个二级域名都有自己的任务队列,不会相互影响。
12.谈一谈HTTP数据传输
对于定长的数据包而言,发送端在发送数据的过程中,需要设置Content-Length,来指明发送数据的长度。
当然了如果采用了Gzip压缩的话,Content-Length设置的就是压缩后的传输长度。
我们还需要知道的是??
Content-Length如果存在并且有效的话,则必须和消息内容的传输长度完全一致,也就是说,如果过短就会截断,过长的话,就会导致超时。
举个例子,如果Content-Length字段的值为1000,而实际消息体的长度只有800,那么服务器端在读取数据时就会认为还有200字节的数据未到达,从而一直等待数据,导致超时。反之,如果消息体的长度超过了Content-Length指定的长度,那么客户端或服务器端在读取数据时就会只读取指定长度的数据,后面的数据会被忽略或截断,导致数据不完整或不正确。
如果采用短链接的话,直接可以通过服务器关闭连接来确定消息的传输长度。
短链接是指在每次通信后关闭连接,与之相对的是长连接,长连接是在一定时间内保持连接状态,可以多次通信。由于短连接在每次通信后关闭连接,所以可以通过服务器关闭连接来确定消息的传输长度。在这种情况下,Content-Length这个字段可以不必要,因为服务器会在通信结束时直接关闭连接,不需要指定传输长度。不过,长连接则需要Content-Length字段来指定消息内容的传输长度,因为服务器无法通过关闭连接来确定消息的传输长度。
那么在HTTP/1.0之前的版本中,Content-Length字段可有可无,因为一旦服务器关闭连接,我们就可以获取到传输数据的长度了。
在HTTP/1.1版本中,如果是Keep-alive的话,chunked优先级高于Content-Length,若是非Keep-alive,跟前面情况一样,Content-Length可有可无。
在HTTP/1.1版本中,对于支持持久连接(Keep-alive)的情况,如果同时存在Transfer-Encoding字段为chunked和Content-Length字段,那么服务器会优先采用chunked编码方式传输数据。因为在chunked编码方式下,服务器无需提前确定消息内容的传输长度,可以逐块传输,这样可以更好地支持流式传输,避免消息长度未知时的超时问题。
而对于不支持持久连接的情况,如HTTP/1.0,或者HTTP/1.1中明确使用了Connection: close标头的请求,则和之前类似,Content-Length字段可有可无,因为一旦服务器关闭连接,客户端就可以获取到传输数据的长度了。
不定长数据
现在采用最多的就是HTTP/1.1版本,来完成传输数据,在保存Keep-alive状态下,当数据是不定长的时候,我们需要设置新的头部字段
Transfer-Encoding: chunked
通过chunked机制,可以完成对不定长数据的处理,当然了,你需要知道的是
如果头部信息中有Transfer-Encoding,优先采用Transfer-Encoding里面的方法来找到对应的长度。
如果设置了Transfer-Encoding,那么Content-Length将被忽视。
使用长连接的话,会持续的推送动态内容。
13.怎么来设置Content-Length
const server = require('http').createServer(); server.on('request', (req, res) => { if(req.url === '/index') { // 设置数据类型 res.setHeader('Content-Type', 'text/plain'); res.setHeader('Content-Length', 10); res.write("你好,使用的是Content-Length设置传输数据形式"); } }) server.listen(3000, () => { console.log("成功启动--TinaTian"); })
const server = require('http').createServer(); server.on('request', (req, res) => { if(req.url === '/index') { // 设置数据类型 res.setHeader('Content-Type', 'text/html; charset=utf8'); res.setHeader('Content-Length', 10); res.setHeader('Transfer-Encoding', 'chunked'); res.write("你好,使用的是Transfer-Encoding设置传输数据形式"); setTimeout(() => { res.write("第一次传输数据给您
"); }, 1000); res.write("骚等一下"); setTimeout(() => { res.write("第一次传输数据给您"); res.end() }, 3000); } }) server.listen(3000, () => { console.log("成功启动--TinaTian"); })
14. cookie 和 session
session: 是一个抽象概念,开发者为了实现中断和继续等操作,将 user agent和 server 之间一对一的交互,抽象为“会话”,进而衍生出“会话状态”,也就是 session 的概念
cookie:它是一个世纪存在的东西,http 协议中定义在 header 中的字段,可以认为是 session 的一种后端无状态实现
现在我们常说的 session,是为了绕开 cookie 的各种限制,通常借助 cookie本身和后端存储实现的,一种更高级的会话状态实现
session 的常见实现要借助cookie来发送 sessionID。
15.介绍一下HTTPS和HTTP区别
HTTPS (Hyper Text Transfer Protocol Secure) 是在 HTTP 基础上加入了安全性保障的协议,它通过 SSL/TLS 加密传输数据,从而提供了身份认证和数据传输的保护。HTTP 和 HTTPS 最主要的区别在于数据传输的安全性。
那么区别有哪些呢??
HTTP 是明文传输协议,HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。
HTTPS比HTTP更加安全,对搜索引擎更友好,利于SEO,谷歌、百度优先索引HTTPS网页。
HTTPS标准端口443,HTTP标准端口80。
HTTPS需要用到SSL证书,而HTTP不用。
我觉得记住以下两点HTTPS主要作用就行??
对数据进行加密,并建立一个信息安全通道,来保证传输过程中的数据安全;
对网站服务器进行真实身份认证。
HTTPS的缺点
证书费用以及更新维护。
HTTPS 降低一定用户访问速度(实际上优化好就不是缺点了)。
HTTPS 消耗 CPU 资源,需要增加大量机器
16 HTTPS握手过程
第一步,客户端给出协议版本号、一个客户端生成的随机数(Client random),以及客户端支持的加密方法
第二步,服务端确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数
第三步,客户端确认数字证书有效,然后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给服务端
第四步,服务端使用自己的私钥,获取客户端发来的随机数(即Premaster secret)。
第五步,客户端和服务端根据约定的加密方法,使用前面的三个随机数,生成"对话密钥"(session key),用来加密接下来的整个对话过程
总结
客户端发起 HTTPS 请求,服务端返回证书,客户端对证书进行验证,验证通过后本地生成用于构造对称加密算法的随机数
通过证书中的公钥对随机数进行加密传输到服务端(随机对称密钥),服务端接收后通过私钥解密得到随机对称密钥,之后的数据交互通过对称加密算法进行加解密。(既有对称加密,也有非对称加密)
17.介绍一个HTTPS工作原理
TLS/SSL 的功能实现主要依赖于三类基本算法:散列函数 、对称加密和非对称加密,其利用非对称加密实现身份认证和密钥协商,对称加密算法采用协商的密钥对数据加密,基于散列函数验证信息的完整性。
加密和解密用同一个秘钥的加密方式叫做对称加密。Client客户端和Server端共用一套密钥,这样子的加密过程似乎很让人理解,但是随之会产生一些问题。
问题一:
WWW万维网有许许多多的客户端,不可能都用秘钥A进行信息加密,这样子很不合理,所以解决办法就是使用一个客户端使用一个密钥进行加密。
问题二:既然不同的客户端使用不同的密钥,那么对称加密的密钥如何传输?
那么解决的办法只能是一端生成一个秘钥,然后通过HTTP传输给另一端,那么这样子又会产生新的问题。
问题三: 这个传输密钥的过程,又如何保证加密?如果被中间人拦截,密钥也会被获取,
那么你会说对密钥再进行加密,那又怎么保存对密钥加密的过程,是加密的过程?
到这里,我们似乎想明白了,使用对称加密的方式,行不通,所以我们需要采用非对称加密??
通过上面的分析,对称加密的方式行不通,那么我们来梳理一下非对称加密。采用的算法是RSA,所以在一些文章中也会看见传统RSA握手,基于现在TLS主流版本是1.2,所以接下来梳理的是TLS/1.2握手过程。
非对称加密中,我们需要明确的点是??
有一对秘钥,公钥和私钥。
公钥加密的内容,只有私钥可以解开,私钥加密的内容,所有的公钥都可以解开,这里说的公钥都可以解开,指的是一对秘钥。
公钥可以发送给所有的客户端,私钥只保存在服务器端。
在这里插入图片描述
步骤一:Client发起一个HTTPS请求,连接443端口。这个过程可以理解成是请求公钥的过程。
步骤二:Server端收到请求后,通过第三方机构私钥加密,会把数字证书(也可以认为是公钥证书)发送给Client。
步骤三:
浏览器安装后会自动带一些权威第三方机构公钥,使用匹配的公钥对数字签名进行解密。
根据签名生成的规则对网站信息进行本地签名生成,然后两者比对。
通过比对两者签名,匹配则说明认证通过,不匹配则获取证书失败。
步骤四:在安全拿到服务器公钥后,客户端Client随机生成一个对称密钥,使用服务器公钥(证书的公钥)加密这个对称密钥,发送给Server(服务器)。
步骤五:Server(服务器)通过自己的私钥,对信息解密,至此得到了对称密钥,此时两者都拥有了相同的对称密钥。
Client用户使用该对称密钥加密'明文内容B',发送给Server(服务器)
Server使用该对称密钥进行解密消息,得到明文内容B。
客户端无法识别传回公钥是中间人的,还是服务器的,这是问题的根本,我们是不是可以通过某种规范可以让客户端和服务器都遵循某种约定呢?那就是通过第三方认证的方式
在HTTPS中,通过证书 + 数字签名来解决这个问题。
在这里插入图片描述
那么客户端是如何去对比两者数字签名的呢?
浏览器会去安装一些比较权威的第三方认证机构的公钥,比如VeriSign、Symantec以及GlobalSign等等。
验证数字签名的时候,会直接从本地拿到相应的第三方的公钥,对私钥加密后的数字签名进行解密得到真正的签名。
然后客户端利用签名生成规则进行签名生成,看两个签名是否匹配,如果匹配认证通过,不匹配则获取证书失败。
数字签名作用
数字签名:将网站的信息,通过特定的算法加密,比如MD5,加密之后,再通过服务器的私钥进行加密,形成加密后的数字签名。
在这里插入图片描述
总结
HTTPS就是使用SSL/TLS协议进行加密传输
大致流程:客户端拿到服务器的公钥(是正确的),然后客户端随机生成一个对称加密的秘钥,使用该公钥加密,传输给服务端,服务端再通过解密拿到该对称秘钥,后续的所有信息都通过该对称秘钥进行加密解密,完成整个HTTPS的流程。
第三方认证,最重要的是数字签名,避免了获取的公钥是中间人的。
18.SSL 连接断开后如何恢复
一共有两种方法来恢复断开的 SSL 连接,一种是使用 session ID,一种是 session ticket。
通过session ID
使用 session ID 的方式,每一次的会话都有一个编号,当对话中断后,下一次重新连接时,只要客户端给出这个编号,服务器如果有这个编号的记录,那么双方就可以继续使用以前的秘钥,而不用重新生成一把。
目前所有的浏览器都支持这一种方法。但是这种方法有一个缺点是,session ID 只能够存在一台服务器上,如果我们的请求通过负载平衡被转移到了其他的服务器上,那么就无法恢复对话。
通过session ticket
另一种方式是 session ticket 的方式,session ticket 是服务器在上一次对话中发送给客户的,这个 ticket 是加密的,只有服务器能够解密,里面包含了本次会话的信息,比如对话秘钥和加密方法等。这样不管我们的请求是否转移到其他的服务器上,当服务器将 ticket 解密以后,就能够获取上次对话的信息,就不用重新生成对话秘钥了。
session ID 和 session ticket。使用 session ID,客户端在 SSL 握手阶段发送保存的会话 ID 给服务器,服务器通过查找保存的 SSL 会话信息来恢复 SSL 会话。使用 session ticket,服务器将 SSL 会话信息加密生成一个会话票据并发送给客户端,客户端保存会话票据,在下次 SSL 握手时发送给服务器,服务器通过解密会话票据来恢复 SSL 会话。
19.谈一谈你对HTTP/2理解
简要概括:http2.0 是基于 1999 年发布的 http1.0 之后的首次更新
提升访问速度(请求资源所需时间更少,访问速度更快,相比 http1.0)
允许多路复用:
多路复用允许同时通过单一的 HTTP/2 连接发送多重请求-响应信息。
多路复用指的是在HTTP/2.0中,客户端与服务器之间只建立一条TCP连接,通过这条连接可以同时发送多个请求和接收多个响应
改 善了:在 http1.1 中,浏览器客户端在同一时间,针对同一域名下的请求有一定数量限 制(连接数量),超过限制会被阻塞
二进制分帧:HTTP2.0 会将所有的传输信息分割为更小的信息或者帧,并对他们进行二 进制编码
HTTP2.0使用二进制格式来分割所有的传输信息成为更小的帧(frame),并对这些帧进行二进制编码。
这种方式相比HTTP/1.x的文本格式更为高效,因为文本格式需要进行解析,而二进制格式只需要读取即可。
通过二进制分帧,HTTP2.0实现了多路复用,允许在一个连接上同时传输多个请求和响应。
由于一个连接上的请求和响应都是通过帧的方式发送和接收,因此可以进行优先级的调整和流量控制,提高了性能和并发度。
首部压缩
HTTP 1.1版本会出现 User-Agent、Cookie、Accept、Server、Range 等字段可能会占用几百甚至几千字节,
而 Body 却经常只有几十字节,所以导致头部偏重。HTTP 2.0 使用 HPACK 算法进行压缩。
HTTP/2.0使用了一种称为“HPACK”的算法来进行首部压缩,它通过维护一个动态表和一个静态表来实现。
动态表包含最近发送的首部字段,静态表包含常见的首部字段,这些表可以在请求和响应之间共享和更新,
从而减少了重复传输的冗余数据。同时,HPACK还使用了一些编码技巧,比如霍夫曼编码,来进一步压缩传输的首部数据。
通过头部压缩,HTTP/2.0能够显著地减少传输的数据量,从而提高传输的效率。
服务器端推送
浏览器发送一个请求,服务器主动向浏览器推送与这个请求相关的资源,这样浏览器就不用发起后续请求。
相比较http/1.1的优势??
推送资源可以由不同页面共享
服务器可以按照优先级推送资源
客户端可以缓存推送的资源
客户端可以拒收推送过来的资源
HTTP2的缺点
TCP 以及 TCP+TLS建立连接的延时,HTTP/2使用TCP协议来传输的,而如果使用HTTPS的话,还需要使用TLS协议进行安全传输,而使用TLS也需要一个握手过程,在传输数据之前,导致我们需要花掉 3~4 个 RTT。
TCP的队头阻塞并没有彻底解决。在HTTP/2中,多个请求是跑在一个TCP管道中的。但当HTTP/2出现丢包时,整个 TCP 都要开始等待重传,那么就会阻塞该TCP连接中的所有请求。
当在HTTP/2中发送多个请求时,这些请求会被分成多个帧并同时发送,这样可以充分利用TCP连接。但是如果一个请求的一个帧丢失了,TCP就需要等待该帧的重传,而此时该TCP连接中的其他请求也会因为该请求的重传而被阻塞。这种情况称为HOL Blocking。
为了解决HOL Blocking问题,HTTP/2采用了一些技术。
例如流量控制、请求优先级和服务器推送等。其中,请求优先级可以帮助服务器决定哪些请求应该被优先处理,从而减少因为某个请求被阻塞而导致的其他请求等待的时间。流量控制可以限制发送方发送数据的速率,防止接收方因为处理不过来而导致的阻塞。而服务器推送则可以让服务器将一些客户端需要的资源主动推送给客户端,从而减少客户端对于服务器的请求,降低整体的延迟。
虽然HTTP/2中仍然存在HOL Blocking问题,但是通过一些技术手段,可以将其最小化,从而提高HTTP/2的性能和吞吐量。
20.HTTP3
Google 在推SPDY的时候就已经意识到了这些问题,于是就另起炉灶搞了一个基于 UDP 协议的“QUIC”协议,让HTTP跑在QUIC上而不是TCP上。主要特性如下:
实现了类似TCP的流量控制、传输可靠性的功能。虽然UDP不提供可靠性的传输,但QUIC在UDP的基础之上增加了一层来保证数据可靠性传输。它提供了数据包重传、拥塞控制以及其他一些TCP中存在的特性
实现了快速握手功能。由于QUIC是基于UDP的,所以QUIC可以实现使用0-RTT或者1-RTT来建立连接,这意味着QUIC可以用最快的速度来发送和接收数据。
集成了TLS加密功能。目前QUIC使用的是TLS1.3,相较于早期版本TLS1.3有更多的优点,其中最重要的一点是减少了握手所花费的RTT个数。
多路复用,彻底解决TCP中队头阻塞的问题。
21 .HTTP/1.0 HTTP1.1 HTTP2.0版本之间的差异
HTTP/1.0、HTTP/1.1 和 HTTP/2.0 是 HTTP 协议的不同版本,它们之间的主要差异包括:
连接管理:HTTP/1.0 每次请求都需要建立一次连接,请求完成后立即断开连接,而 HTTP/1.1 支持持久连接,可以在一次连接中传送多个请求和响应。HTTP/2.0 更进一步,支持多路复用,可以在同一连接中并发地传送多个请求和响应,从而减少了连接建立和关闭的开销。
压缩方式:HTTP/1.0 和 HTTP/1.1 未对请求和响应的头部进行压缩,而 HTTP/2.0 支持对头部进行 HPACK 压缩,可以减少传输的数据量,提高传输效率。
二进制格式:HTTP/1.0 和 HTTP/1.1 使用 ASCII 码表示请求和响应,而 HTTP/2.0 使用二进制格式表示请求和响应,可以减少解析的开销。
流控制:HTTP/2.0 支持流控制机制,可以在发送请求和响应时进行控制,避免因过多的请求和响应导致的资源竞争和拥塞。
服务器推送:HTTP/2.0 支持服务器推送机制,可以在客户端请求资源时主动将相关资源推送给客户端,从而减少客户端的请求次数,提高性能。
总的来说,HTTP/2.0 相对于 HTTP/1.0 和 HTTP/1.1 AUfXpKH3HhwRznxTSrWvMJTaAXhT7W3s5i1fgxC5vaES
22.DNS如何工作的
DNS 的作用就是通过域名查询到具体的 IP。DNS 协议提供的是一种主机名到 IP 地址的转换服务,就是我们常说的域名系统。是应用层协议,通常该协议运行在UDP协议之上,使用的是53端口号。
当你在浏览器中想访问 www.google.com 时,会通过进行以下操作:
本地客户端向服务器发起请求查询 IP 地址
查看浏览器有没有该域名的 IP 缓存
查看操作系统有没有该域名的 IP 缓存
查看 Host 文件有没有该域名的解析配置
如果这时候还没得话,会通过直接去 DNS 根服务器查询,这一步查询会找出负责 com 这个一级域名的服务器
然后去该服务器查询 google.com 这个二级域名
接下来查询 www.google.com 这个三级域名的地址
返回给 DNS 客户端并缓存起来
在这里插入图片描述这张图很生动的展示了DNS在本地DNS服务器是如何查询的,一般向本地DNS服务器发送请求是递归查询的。
本地 DNS 服务器向其他域名服务器请求的过程是迭代查询的过程??
在这里插入图片描述递归查询和迭代查询
递归查询指的是查询请求发出后,域名服务器代为向下一级域名服务器发出请求,最后向用户返回查询的最终结果。使用递归 查询,用户只需要发出一次查询请求。
迭代查询指的是查询请求后,域名服务器返回单次查询的结果。下一级的查询由用户自己请求。使用迭代查询,用户需要发出 多次的查询请求。
所以一般而言,本地服务器查询是递归查询,而本地 DNS 服务器向其他域名服务器请求的过程是迭代查询的过程
23.DNS缓存
DNS缓存是一种存储DNS查询结果的机制,它能够提高DNS查询速度,减少网络流量并降低DNS服务器的负载。当一个域名被访问时,DNS服务器会首先检查本地缓存,如果有对应的解析记录,则直接返回,否则将向上级DNS服务器发起请求,以获取解析记录,并将其缓存在本地服务器上。这样,当再次访问该域名时,DNS服务器就可以直接返回缓存中的解析结果,而不需要再次向上级服务器请求。DNS缓存通常会设定一个生存时间(TTL),在这个时间内,缓存中的解析结果将被视为有效,超过这个时间则需要重新向上级DNS服务器发起请求获取最新的解析结果。
缓存也很好理解,在一个请求中,当某个DNS服务器收到一个DNS回答后,它能够回答中的信息缓存在本地存储器中。
返回的资源记录中的 TTL 代表了该条记录的缓存的时间。
DNS实现负载平衡
当用户发起网站域名的 DNS 请求的时候,DNS 服务器返回这个域名所对应的服务器 IP 地址的集合
在每个回答中,会循环这些 IP 地址的顺序,用户一般会选择排在前面的地址发送请求。
以此将用户的请求均衡的分配到各个不同的服务器上,这样来实现负载均衡
24.DNS 为什么使用 UDP 协议作为传输层协议?
DNS 使用 UDP 协议作为传输层协议的主要原因是为了避免使用 TCP 协议时造成的连接时延。
UDP(User Datagram Protocol)协议是一种无连接、无状态的协议,不需要在发送数据前建立连接。与之相比,TCP(Transmission Control Protocol)协议需要在发送数据前建立连接,因此会带来一定的连接时延。
DNS的查询请求和响应都很短小,通常不超过512字节,而且DNS服务器需要尽可能地快速响应查询请求,因此采用UDP协议能够在传输效率和实时性方面提供更好的性能,同时避免了建立连接时延对查询速度的影响。
然而,UDP协议的无连接特性也导致了其可靠性较差,容易出现数据丢失或乱序等问题。因此,DNS在使用UDP协议时也会采取一些机制来保证数据的可靠性,比如使用重传和超时机制来应对数据丢失和延迟。
总结
DNS域名系统,是应用层协议,运行UDP协议之上,使用端口43。
查询过程,本地查询是递归查询,依次通过浏览器缓存 —>> 本地hosts文件 —>> 本地DNS解析器 —>>本地DNS服务器 —>> 其他域名服务器请求。 接下来的过程就是迭代过程。
递归查询一般而言,发送一次请求就够,迭代过程需要用户发送多次请求。
25.短轮询、长轮询和 WebSocket 间的区别
短轮询、长轮询和 WebSocket 都是客户端和服务器之间进行通信的方式,但是它们的实现方式和使用场景不同。
短轮询(Short Polling):
短轮询是一种最简单的轮询方式,客户端定期向服务器发送 HTTP 请求,服务器在接收到请求后立即返回响应,告诉客户端是否有新数据。如果服务器没有新数据,客户端需要再次发送请求,这样客户端就需要不停地轮询服务器。这种方式会导致大量的网络请求和带宽消耗,不适合大规模应用。
优缺点??
优点是比较简单,易于理解。
缺点是这种方式由于需要不断的建立 http 连接,严重浪费了服务器端和客户端的资源。当用户增加时,服务器端的压力就会变大,这是很不合理的。
长轮询(Long Polling):
长轮询是一种改进的轮询方式,客户端向服务器发送请求后,服务器不会立即返回响应,而是将请求挂起,等待有新数据时再返回响应。这样可以减少服务器的负担和网络带宽的消耗。客户端在收到响应后会立即发送新的请求,以便下一次接收数据。长轮询适用于实时数据的应用场景,如即时通讯、消息推送等。
优缺点??
长轮询和短轮询比起来,它的优点是明显减少了很多不必要的 http 请求次数,相比之下节约了资源。
长轮询的缺点在于,连接挂起也会导致资源的浪费
WebSocket:
WebSocket 是一种基于 TCP 协议的全双工通信协议,它可以在客户端和服务器之间建立一条持久的连接,实现实时双向通信。WebSocket 不需要像 HTTP 请求那样携带大量的请求头信息,而且客户端和服务器之间的通信也不需要通过中间代理服务器,因此 WebSocket 具有更低的网络延迟和更高的传输效率。WebSocket 适用于实时通信、在线游戏、音视频直播等应用场景。
WebSocket 是一种在 Web 应用程序中实现双向通信的协议,它具有以下优点和缺点:
优点:
实时性好:WebSocket 支持双向通信,实时性更好,不需要客户端轮询服务器。
减少数据传输量:WebSocket 协议采用了更加轻量级的数据帧格式,相比 HTTP 协议,传输数据时更加高效。
提供更好的错误处理机制:WebSocket 可以通过事件回调机制提供更好的错误处理机制。
支持跨域:WebSocket 支持跨域通信,可以让 Web 应用程序在不同域之间进行实时双向通信。
可以使用 SSL/TLS 协议进行加密。
缺点:
WebSocket 在旧版浏览器中的兼容性问题:旧版的浏览器不支持 WebSocket 协议,需要使用轮询等其他技术来实现实时通信。
长连接对服务器资源的消耗:WebSocket 协议需要维护长连接,长时间保持连接对服务器资源有一定的消耗。
不支持浏览器的后退按钮:由于 WebSocket 协议使用了长连接,浏览器的后退按钮无法撤销已经建立的 WebSocket 连接。
不支持代理服务器:由于 WebSocket 协议使用了自定义的数据帧格式,不同代理服务器的实现可能不同,无法保证协议的一致性,从而导致连接失败。
26.说一说正向代理和反向代理
正向代理
我们常说的代理也就是指正向代理,正向代理的过程,它隐藏了真实的请求客户端,服务端不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替来请求。
反向代理
这种代理模式下,它隐藏了真实的服务端,当我们向一个网站发起请求的时候,背后可能有成千上万台服务器为我们服务,具体是哪一台,我们不清楚,我们只需要知道反向代理服务器是谁就行,而且反向代理服务器会帮我们把请求转发到真实的服务器那里去,一般而言反向代理服务器一般用来实现负载平衡。
27.负载平衡的两种实现方式?
一种是使用反向代理的方式,用户的请求都发送到反向代理服务上,然后由反向代理服务器来转发请求到真实的服务器上,以此来实现集群的负载平衡。
DNS 可以实现负载平衡的方法是将多个服务器的 IP 地址绑定到同一个域名下,并通过 DNS 解析来将请求分发到不同的服务器上,从而达到负载均衡的目的。
28.介绍一下Connection:keep-alive
什么是keep-alive
我们知道HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每个请求/应答客户和服务器都要新建一个连接,完成 之后立即断开连接(HTTP协议为无连接的协议);
当使用Keep-Alive模式(又称持久连接、连接重用)时,Keep-Alive功能使客户端到服 务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。
为什么要使用keep-alive
keep-alive技术的创建目的,能在多次HTTP之前重用同一个TCP连接,从而减少创建/关闭多个 TCP 连接的开销
在这里插入图片描述
客户端如何开启
在HTTP/1.0协议中,默认是关闭的,需要在http头加入"Connection: Keep-Alive”,才能启用Keep-Alive;
Connection: keep-alive
http 1.1中默认启用Keep-Alive,如果加入"Connection: close “,才关闭。
Connection: close
目前大部分浏览器都是用http1.1协议,也就是说默认都会发起Keep-Alive的连接请求了,所以是否能完成一个完整的Keep- Alive连接就看服务器设置情况。
29.http/https 协议总结
1.0 协议缺陷:
无法复用链接,完成即断开,重新慢启动和 TCP 3次握手
head of line blocking: 线头阻塞,导致请求之间互相影响
1.1 改进:
长连接(默认 keep-alive),复用
host 字段指定对应的虚拟站点
新增功能:
断点续传
身份认证
状态管理
cache 缓存
Cache-Control
Expires
Last-Modified
Etag
2.0:
多路复用
二进制分帧层: 应用层和传输层之间
首部压缩
服务端推送
https: 较为安全的网络传输协议
证书(公钥)
SSL 加密
端口 443
TCP:
三次握手
四次挥手
滑动窗口: 流量控制
拥塞处理
慢开始
拥塞避免
快速重传
快速恢复
缓存策略: 可分为 强缓存 和 协商缓存
Cache-Control/Expires: 浏览器判断缓存是否过期,未过期时,直接使用强缓存,Cache-Control的 max-age 优先级高于 Expires
当缓存已经过期时,使用协商缓存
唯一标识方案: Etag(response 携带) & If-None-Match(request携带,上一次返回的 Etag): 服务器判断资源是否被修改
最后一次修改时间: Last-Modified(response) & If-Modified-Since(request,上一次返回的Last-Modified)
如果一致,则直接返回 304 通知浏览器使用缓存
如不一致,则服务端返回新的资源
Last-Modified 缺点:
周期性修改,但内容未变时,会导致缓存失效
最小粒度只到 s, s 以内的改动无法检测到
Etag 的优先级高于Last-Modified
30. TCP为什么要三次握手
客户端和服务端都需要直到各自可收发,因此需要三次握手
第一次握手成功让服务端知道了客户端具有发送能力
第二次握手成功让客户端知道了服务端具有接收和发送能力,但此时服务端并不知道客户端是否接收到了自己发送的消息
所以第三次握手就起到了这个作用。
在这里插入图片描述
你可以能会问,2 次握手就足够了?。但其实不是,因为服务端还没有确定客户端是否准备好了。比如步骤 3 之后,服务端马上给客户端发送数据,这个时候客户端可能还没有准备好接收数据。因此还需要增加一个过程。
在这里插入图片描述举例:已失效的连接请求报文段
client发送了第一个连接的请求报文,但是由于网络不好,这个请求没有立即到达服务端,而是在某个网络节点中滞留了,直到某个时间才到达server
本来这已经是一个失效的报文,但是server端接收到这个请求报文后,还是会想client发出确认的报文,表示同意连接。
假如不采用三次握手,那么只要server发出确认,新的建立就连接了,但其实这个请求是失效的请求,client是不会理睬server的确认信息,也不会向服务端发送确认的请求
但是server认为新的连接已经建立起来了,并一直等待client发来数据,这样,server的很多资源就没白白浪费掉了
采用三次握手就是为了防止这种情况的发生,server会因为收不到确认的报文,就知道client并没有建立连接。这就是三次握手的作用。
三次握手过程中可以携带数据吗
AUfXpKH3HhwRznxTSrWvMJTaAXhT7W3s5i1fgxC5vaES
而第三次握手,此时客户端已经处于 ESTABLISHED (已建立连接状态) ,对于客户端来说,已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据也是没问题的。
31.为什么建立连接只通信了三次,而断开连接却用了四次?
客户端要求断开连接,发送一个断开的请求,这个叫作(FIN)
服务端收到请求,然后给客户端一个 ACK,作为 FIN 的响应。
这里你需要思考一个问题,可不可以像握手那样马上传 FIN 回去?
其实这个时候服务端不能马上传 FIN,因为断开连接要处理的问题比较多,比如说服务端可能还有发送出去的消息没有得到
ACK;也有可能服务端自己有资源要释放。因此断开连接不能像握手那样操作——将两条消息合并。所以,服务端经过一个等待,确定可以关闭连接了,再发一条
FIN 给客户端。
客户端收到服务端的 FIN,同时客户端也可能有自己的事情需要处理完,比如客户端有发送给服务端没有收到 ACK
的请求,客户端自己处理完成后,再给服务端发送一个 ACK。
在这里插入图片描述
为了确保数据能够完成传输。因为当服务端收到客户端的 FIN 报文后,发送的 ACK 报文只是用来应答的,并不表示服务端也希望立即关闭连接。
当只有服务端把所有的报文都发送完了,才会发送 FIN 报文,告诉客户端可以断开连接了,因此在断开连接时需要四次挥手。
32 为什么要有 WebSocket
其实 WebSocket 与 HTTP/2 一样,都是为了解决 HTTP 某方面的缺陷而诞生的。HTTP/2 针对的是“队头阻塞”,而 WebSocket 针对的是“请求 - 应答”通信模式。
那么,“请求 - 应答”有什么不好的地方呢?
“请求 - 应答”是一种“半双工”的通信模式,虽然可以双向收发数据,但同一时刻只能一个方向上有动作,传输效率低。更关键的一点,它是一种“被动”通信模式,服务器只能“被动”响应客户端的请求,无法主动向客户端发送数据。
虽然后来的 HTTP/2、HTTP/3 新增了 Stream、Server Push 等特性,但“请求 - 应答”依然是主要的工作方式。这就导致 HTTP 难以应用在动态页面、即时消息、网络游戏等要求“实时通信”的领域。
在 WebSocket 出现之前,在浏览器环境里用 JavaScript 开发实时 Web 应用很麻烦。因为浏览器是一个“受限的沙盒”,不能用 TCP,只有 HTTP 协议可用,所以就出现了很多“变通”的技术,“轮询”(polling)就是比较常用的的一种。
简单地说,轮询就是不停地向服务器发送 HTTP 请求,问有没有数据,有数据的话服务器就用响应报文回应。如果轮询的频率比较高,那么就可以近似地实现“实时通信”的效果。
但轮询的缺点也很明显,反复发送无效查询请求耗费了大量的带宽和 CPU 资源,非常不经济。
所以,为了克服 HTTP“请求 - 应答”模式的缺点,WebSocket 就“应运而生”了。
33.WebSocket 的特点
WebSocket 是一个真正“全双工”的通信协议,与 TCP 一样,客户端和服务器都可以随时向对方发送数据
WebSocket 采用了二进制帧结构,语法、语义与 HTTP完全不兼容,但因为它的主要运行环境是浏览器,为了便于推广和应用,就不得不“搭便车”,在使用习惯上尽量向 HTTP靠拢,这就是它名字里“Web”的含义。
服务发现方面,WebSocket 没有使用 TCP 的“IP 地址 + 端口号”,而是延用了 HTTP 的 URI
格式,但开头的协议名不是“http”,引入的是两个新的名字:“ws”和“wss”,分别表示明文和加密的 WebSocket 协议。
WebSocket 的默认端口也选择了 80 和 443,因为现在互联网上的防火墙屏蔽了绝大多数的端口,只对 HTTP 的 80、443
端口“放行”,所以 WebSocket 就可以“伪装”成 HTTP 协议,比较容易地“穿透”防火墙,与服务器建立连接。
34.WebSocket的好处:
双向通信:WebSocket允许客户端和服务器之间进行实时的双向通信,这是HTTP协议无法实现的。
实时数据传输:WebSocket允许实时地传输数据,而不像HTTP请求需要经过一段时间才能得到响应。
减少网络流量:WebSocket可以通过在客户端和服务器之间建立单个连接来减少网络流量,而不是像HTTP请求那样需要多次建立连接。
更好的性能:WebSocket可以减少服务器的负载,因为客户端不需要经常请求数据,而是在需要时直接获取数据。
更好的用户体验:由于WebSocket允许实时数据传输,因此可以提供更好的用户体验,例如实时聊天、多人协作和在线游戏等。
35.WebSocket 的握手
WebSocket协议使用HTTP协议的握手过程来建立连接。以下是WebSocket握手的步骤:
客户端向服务器发送一个HTTP请求,请求的头信息中包含"Upgrade"和"Connection"字段,告诉服务器它希望升级到WebSocket协议。
服务器接收到请求后,检查请求头中是否包含"Upgrade"和"Connection"字段,如果存在,则表示客户端希望升级到WebSocket协议。服务器会发送一个响应,包含"Upgrade"和"Connection"字段,并将"Upgrade"字段的值设置为"websocket"。
客户端接收到服务器的响应后,检查响应头中是否包含"Upgrade"和"Connection"字段,如果存在,则表示协议升级成功。此时客户端和服务器之间建立了WebSocket连接。
客户端和服务器之间的数据传输将通过WebSocket协议进行,可以直接发送WebSocket数据帧,而不需要经过HTTP请求和响应的过程。
总之,WebSocket协议使用HTTP协议的握手过程来建立连接,这使得它可以在现有的Web基础设施上进行部署,并提供实时的双向通信能力。
WebSocket 的握手是一个标准的 HTTP GET 请求,但要带上两个协议升级的专用头字段:
“Connection: Upgrade”,表示要求协议“升级”;
“Upgrade: websocket”,表示要“升级”成 WebSocket 协议。
另外,为了防止普通的 HTTP 消息被“意外”识别成 WebSocket,握手消息还增加了两个额外的认证用头字段(所谓的“挑战”,Challenge):
Sec-WebSocket-Key:一个 Base64 编码的 16 字节随机数,作为简单的认证密钥;
Sec-WebSocket-Version:协议的版本号,当前必须是 13。
这两个头字段分别是"Sec-WebSocket-Key"和"Sec-WebSocket-Accept"。在WebSocket握手期间,客户端会生成一个随机的Sec-WebSocket-Key,然后将其发送到服务器。服务器收到这个Key之后,会使用一种特定的算法将其转换为一个"Sec-WebSocket-Accept"值,并将该值作为响应头中的一个字段发送回客户端。
客户端会将收到的"Sec-WebSocket-Accept"值与自己计算得到的期望值进行比较。如果两个值相等,那么握手成功,客户端和服务器之间建立了WebSocket连接。这种挑战-响应机制可以防止普通的HTTP请求被错误地识别为WebSocket请求。
值得注意的是,这种挑战-响应机制并不提供任何安全保证,只是用于识别WebSocket请求的。如果需要进行安全验证,可以使用WebSocket的子协议,如WebSocket Secure(WSS)或其他安全协议。
在这里插入图片描述
服务器收到 HTTP 请求报文,看到上面的四个字段,就知道这不是一个普通的 GET 请求,而是 WebSocket 的升级请求,于是就不走普通的 HTTP 处理流程,而是构造一个特殊的“101 Switching Protocols”响应报文,通知客户端,接下来就不用 HTTP 了,全改用 WebSocket 协议通信
小结
浏览器是一个“沙盒”环境,有很多的限制,不允许建立 TCP 连接收发数据,而有了 WebSocket,我们就可以在浏览器里与服务器直接建立“TCP 连接”,获得更多的自由。
不过自由也是有代价的,WebSocket 虽然是在应用层,但使用方式却与“TCP Socket”差不多,过于“原始”,用户必须自己管理连接、缓存、状态,开发上比 HTTP 复杂的多,所以是否要在项目中引入 WebSocket 必须慎重考虑。
HTTP 的“请求 - 应答”模式不适合开发“实时通信”应用,效率低,难以实现动态页面,所以出现了 WebSocket;
WebSocket 是一个“全双工”的通信协议,相当于对 TCP 做了一层“薄薄的包装”,让它运行在浏览器环境里;
WebSocket 使用兼容 HTTP 的 URI 来发现服务,但定义了新的协议名“ws”和“wss”,端口号也沿用了 80 和 443;
WebSocket 使用二进制帧,结构比较简单,特殊的地方是有个“掩码”操作,客户端发数据必须掩码,服务器则不用;
WebSocket 利用 HTTP 协议实现连接握手,发送 GET 请求要求“协议升级”,握手过程中有个非常简单的认证机制,目的是防止误连接。
36.UDP和TCP有什么区别
在这里插入图片描述
TCP协议在传送数据段的时候要给段标号;UDP协议不需要
TCP协议在传送数据时,将数据分割成若干个数据段,并为每个数据段分配一个序号(即段标号)。这个序号是一个32位的数字,用于唯一标识一个数据段,确保数据的有序传输和可靠传输。
TCP使用序号来解决数据包乱序、丢失、重复等问题。接收方通过检查序号,可以确定收到的数据段是否是按照发送方发送的顺序到达的,以及是否有丢失或重复的数据段
TCP协议可靠;UDP协议不可靠
TCP协议是一种面向连接的协议,这意味着在数据传输前,发送方和接收方需要先建立一个连接。UDP协议采用无连接的方式进行数据传输,发送方直接向接收方发送数据,不需要事先建立连接。
TCP协议负载较高,采用虚电路;UDP采用无连接
虚电路(Virtual Circuit)是一种逻辑上的连接,用于在网络中模拟出传输数据时需要的一条物理电路。虚电路可以在网络中建立起一个专门的逻辑通道,用于在发送方和接收方之间传输数据,类似于电话中的虚拟通路。
TCP协议的发送方要确认接收方是否收到数据段(3次握手协议)
TCP协议采用窗口技术和流控制
窗口技术(Windowing)是指在TCP连接中,发送方和接收方之间维护一个窗口大小,用于控制数据的发送和接收速率。窗口大小指的是在不进行确认操作的情况下,允许发送方向接收方发送数据的字节数量。通过控制窗口大小,可以避免网络拥塞、提高传输效率和可靠性。
在TCP连接建立之后,发送方和接收方会互相通知对方它们的窗口大小。当发送方发送数据包时,接收方会对收到的数据包进行确认,并告诉发送方它当前的可用窗口大小,发送方需要根据接收方的窗口大小调整发送数据包的数量和速率。如果接收方窗口变小,发送方会减少发送数据包的数量,如果接收方窗口变大,发送方则可以增加发送数据包的数量。
流控制(Flow Control)是指通过控制数据发送速率,以避免接收方处理过多的数据而导致溢出。在TCP协议中,接收方可以向发送方发送窗口大小,限制发送方发送数据的速率,避免发送过快而导致接收方无法处理的情况。
流控制和窗口技术的结合可以有效地保证TCP连接的可靠性和效率,避免了数据传输过程中的拥塞和数据丢失问题