This commit is contained in:
Dragon
2020-10-19 20:26:04 +08:00
parent 0bbdc1d9d2
commit a6fff83b0d
15 changed files with 16288 additions and 2 deletions

View File

@@ -0,0 +1,923 @@
# 备注
1、打【】的是有印象能大致说出来即可但是没打【】的也不要背理解性记忆。
2、如果有知识点有的博客讲的很清楚我就直接贴链接了。
3、《计算机网络7》是一本很好的书讲的很详细而且不难懂读者有时间的话建议看一下。
4、如果有错误欢迎在评论区指正
> 1、本人正在准备秋招秋招完之后会持续更新博客。这些总结的部分也是准备面试期间看了很多很多博客写下来的。
> 2、本人博客https://youthlql.gitee.io/
> 3、等忙完秋招会陆续更新一些内容。喜欢的朋友可以收藏一下博客
>
# 补充
这里面的就是讲的比较详细的博客
## 关于计网比较好的博客
https://blog.csdn.net/ThinkWon/article/details/104903925
https://www.cnblogs.com/xjtu-lyh/p/12439036.html
## 三次挥手,四次握手
https://blog.csdn.net/qzcsu/article/details/72861891
## DNS解析
https://blog.csdn.net/weixin_40470303/article/details/80642190
## http1.0http1.1http2.0介绍
https://segmentfault.com/a/1190000016656529
## https建立链接过程
https://blog.csdn.net/iispring/article/details/51615631
## IO的一些博客
https://blog.csdn.net/sehanlingfeng/article/details/78920423
https://www.cnblogs.com/felixzh/p/10345929.html
# OSI七层模型与TCP/IP 五层模型
## 物理层
物理层考虑的是怎样才能在连接各种计算机的传输介质上传输数据比特流。现有的计算机网络中的硬件设备和传输媒体(介质)的种类非常多,而通信手段也有许多不同方式。物理层的作用正是要尽可能地屏蔽掉这些传输媒体和硬件设备的差异,使物理层上面的数据链路层感觉不到这些差异,这样就可使数据链路层只考虑如何完成本层的协议和服务,而不必考虑网络具体的传输媒体和通信手段是什么。
> 参考《计算机网络7》P51
## 数据链路层
### 概念
数据链路层研究的是分组怎样从一台主机传送到另一台主机,但并不经过路由器转发。从整个互联网来看,局域网仍属于数据链路层的范围。数据传送单位是帧。
**简单的过程:**
1、在两个相邻节点之间传送数据时数据链路层将网络层交下来的**IP 数据报**添加首部和尾部组装成帧****在两个相邻节点间的链路上传送帧**。**每一帧包括数据和必要的控制信息【如同步信息,地址信息,差错控制等】。
2、数据链路层在收到一个帧后通过控制信息检测收到的帧中是否有差错如果没有就可从中提出**IP数据报**部分,上交给网络层**。**如果发现差错,数据链路层就简单地丢弃这个出了差错的帧,以避免继续在网络中传送下去白白浪费网络资源 【在接收数据时,控制信息使接收端能够知道一个帧从哪个比特开始和到哪个比特结束。控制信息还使接收端能够检测到所收到的帧中有误差错。如果发现差错,数据链路层就简单地丢弃这个出了差错的帧,以避免继续在网络中传送下去白白浪费网络资源。如果需要改正数据在链路层传输时出现差错(这就是说,数据链路层不仅要检错,而且还要纠错),那么就要采用可靠性传输协议来纠正出现的差错。这种方法会使链路层的协议复杂些】
### 一些小细节
**数据链路层使用的信道主要有两种:**
①点对点信道
②广播信道
**三个基本问题:**
封装成帧、透明传输和差错检测。
> 更细致的看《计算机网络7》 P82
## 网络层
1、在计算机网络中进行通信的两个计算机之间可能会经过很多个数据链路也可能还要经过很多通信子网。网络层的任务就是选择合适的网间路由和交换结点确保数据及时传送。网络层向上只提供简单灵活的、无连接的、尽最大努力交付的IP数据报服务。【其实数据报或IP数据报就是我们经常使用的“分组”】
2、网络层在发送分组时不需要先建立连接没有给分组进行上编号所传送的分组可能出错、丢失、重复和失序。如果主机即端系统中的进程之间的通信需要是可靠的那么就由网络的主机中的运输层负责包括差错处理、流量控制等
> 更多细节-->《计算机网络7》 P124
## 运输层
1、运输层的主要任务就是负责向两台主机的进程之间提供通用的数据传输服务。
2、运输层有一个很重要的功能 复用和分用。这里的“复用"是指在发送方不同的应用进程都可以使用同一个运输层协议传送数据(当然需要加上适当的首部),而“分用”是指接收方的运输层在剥去报文的首部后能够把这些数据正确交付目的应用进程
3、运输层向高层用户屏蔽了下面网络核心的细节【如网络拓扑、所采用的路由选择协议等】**它使应用进程看见的就是好像在两个运输层实体之间有一条端到端的逻辑通信信道**。但这条逻辑通信信道对上层的表现却因运输层使用的不同协议而有很大的差别。当运输层釆用面向连接的TCP协议时尽管下面的网络层是不可靠的只提供尽最大努力服务但这种逻辑通信信道就相当于一条全双工的可靠信道。但当运输层采用无连接的udp协议时这种逻辑通信信道仍然是一条不可靠信道。
## 应用层
(在上一章,我们巳学习了运输层为应用进程提供了端到端的通信服务)。
**1.** **不同的网络应用的应用进程之间,还需要有不同的通信规则。因此在运输层协议之上,还需要有应用层协议****。**
**2.** **每个应用层协议都是为了解决某一类应用问题,**(而问题的解决又必须通过位于不同主机中的多个应用进程之间的通信和协同工作来完成)**。应用进程之间的这种通信必须遵循严格的规则。应用层的具体内容就是精确定义这些通信规则。**
3.**运输层是两台主机间进程的交互。应用层是为了更加细化不同网络应用的交互规则。**
# 常见应用层协议和运输层、网络层协议
## 各层协议
**应用层:**HTTP(超文本传输协议) DNS(域名系统) FTP(文件传输协议) SMTP(简单邮件传送协议)
**运输层:**TCP UDP
**网络层:** IP, ARP(地址解析协议)--> 见《计网7》P134
## 硬件如路由器之类在哪一层
- 路由器在网络层,用来进行路由选择
# TCP与UDP区别和应用场景基于TCP的协议有哪些基于UDP的有哪些
## 区别+应用场景
<img src="https://cdn.jsdelivr.net/gh/youthlql/lql_img/computer_network/summary/0001.png" width=90%>
**总结:**
1、UDP的主要特点是
①无连接②尽最大努力交付③面向报文④无拥塞控制⑤支持一对一,一对多,多对一和多对多的交互通信⑥首部开销小(只有四个字段:源端口,目的端口,长度和检验和)
2、TCP的主要特点是
①面向连接②每一条TCP连接只能是一对一的③提供可靠交付④提供全双工通信⑤面向字节流
## 基于TCP的协议有哪些基于UDP的有哪些
**TCP**
HTTP, 超文本传输协议
FTP, 文件传输协议
SMTP,简单邮件传输协议,用来发送电子邮件
SSH 安全外壳协议,用于加密安全登陆
**UDP**
DHCP协议动态主机配置协议动态配置IP地址
NTP协议网络时间协议用于网络时间同步
RIP路由选择协议
DNS
# TCP可靠传输的保证拥塞控制目的和过程
## 如何保证可靠传输
TCP通过三次握手建立可靠连接
①数据被分割成 TCP 认为最适合发送的数据包。TCP 给发送的每一个包进行编号,接收方对数据包进行排序,将有序数据传送给应用层。**TCP通过序列号和确认应答提高可靠性**
②校验和: TCP 将保持它首部和数据的检验和。这是一个端到端的检验和目的是检测数据在传输过程中的任何变化。如果收到端的校验和有差错TCP 将丢弃这个报文段和不确认收到此报文段。
③流量控制: TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。 接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。
④拥塞控制: 当网络拥塞时,减少数据的发送。
⑤ARQ协议分为停止等待ARQ协议和连续ARQ协议
5.1 它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。
5.2 超时重传::当 TCP 发出一个报文段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。
5.3 TCP 的接收端会丢弃重复的数据
## ARQ
- 停止等待ARQ它的基本原理就是每发完一个分组就停止发送等待对方确认回复ACK。如果过了一段时间超时时间后还是没有收到 ACK 确认说明没有发送成功需要重新发送直到收到确认后再发下一个分组。停止等待协议中超时重传是指只要超过一段时间仍然没有收到确认就重传前面发送过的分组认为刚才发送过的分组丢失了。因此每发送完一个分组需要设置一个超时计时器其重转时间应比数据在分组传输的平均往返时间更长一些。这种自动重传方式常称为自动重传请求ARQ。另外在停止等待协议中若收到重复分组就丢弃该分组但同时还要发送确认。
- 连续ARQ协议(流水线的传输方式)可提高信道利用率。发送维持一个发送窗口,凡位于发送窗口内的分组可连续发送出去,而不需要等待对方确认。接收方一般采用累积确认,对按序到达的最后一个分组发送确认,表明到这个分组位置的所有分组都已经正确收到了。
## 拥塞控制
**目的:**
拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。
**过程:**
为了进行拥塞控制TCP 发送方要维持一个 拥塞窗口(cwnd) 的状态变量。拥塞控制窗口的大小取决于网络的拥塞程度,并且动态变化。发送方让自己的发送窗口取为拥塞窗口和接收方的接受窗口中较小的一个。**慢开始和拥塞避免都是基于窗口的拥塞控制**。
**区别:**
> https://blog.csdn.net/ligupeng7929/article/details/79597423
* **慢开始:** 慢开始算法的思路是当主机开始发送数据时如果立即把大量数据字节注入到网络那么可能会引起网络阻塞因为现在还不知道网络的符合情况。经验表明较好的方法是先探测一下即由小到大逐渐增大发送窗口也就是由小到大逐渐增大拥塞窗口数值。cwnd初始值为1每经过一个传播轮次cwnd加倍。
* **拥塞避免:** 拥塞避免算法的思路是让拥塞窗口cwnd缓慢增大即每经过一个往返时间RTT就把发送放的cwnd加1.
- 为了防止拥塞窗口cwnd增长过大引起网络拥塞还需要设置一个慢开始门限ssthresh状态变量如何设置ssthresh。慢开始门限ssthresh的用法如下
当 cwnd < ssthresh 时,使用上述的慢开始算法。
当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。
当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞控制避免算法。
- 拥塞避免算法让拥塞窗口cwnd缓慢地增大即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1而不是加倍。这样拥塞窗口cwnd按线性规律缓慢增长比慢开始算法的拥塞窗口增长速率缓慢得多。
**快重传和快恢复:**
1、**快重传**算法首先要求接收方每收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时才进行捎带确认。
2、发送方知道现在只是丢失了个别的报文段。于是不启动慢开始而是执行**快恢复算法**。这时发送方调整门限值ssthresh= (cwnd/2=8,同时设置拥塞窗口cwnd = ssthresh=8 ,并开始执行拥塞避免算法。
3、请注意也有的快恢复实现是把快恢复开始时的拥塞窗口cwnd值再增大一一些(增大3个报文段的长度)即等于新的ssthresh + 3 x MSS。这样做的理由是:既然发送方收到3个重复的确认就表明有3个分组已经离开了网络。这3个分组不再消耗网络的资源而是停留在接收方的缓存中(接收方发送出3个重复的确认就证明了这个事实)。可见现在网络中并不是堆积了分组而是减少了3个分组。因此可以适当把拥塞窗口扩大些。
在采用快恢复算法时慢开始算法只是在TCP连接建立时和网络出现超时时才使用。
<img src="https://cdn.jsdelivr.net/gh/youthlql/lql_img/computer_network/summary/0002.png" width=80%>
## 为什么要进行流量控制
一般来说,我们总是希望数据传输更快一些。但如果发送方把数据发送的过快,接收方就可能来不及接收,这就会造成数据的丢失(丢包)。
# TCP粘包现象原因和解决方法
## 原因
1.UDP协议的保护消息边界使得每一个消息都是独立的
2.而tcp是基于流的传输流传输却把数据当作一串数据流他不认为数据是一个一个的消息
3.发送端需要等缓冲区满才发送出去,造成粘包
4.接收方不及时接收缓冲区的包,造成多个包粘包
具体点:
1发送方引起的粘包是由TCP协议本身造成的TCP为提高传输效率发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少通常TCP会根据优化算法把这些数据合成一包后一次发送出去这样接收方就收到了粘包数据。
2接收方引起的粘包是由于接收方用户进程不及时接收数据从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区用户进程从该缓冲区取数据若下一包数据到达时前一包数据尚未被用户进程取走则下一包数据放到系统接收缓冲区时就接到前一包数据之后而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据这样就一次取到了多包数据。
## 解决方法
1对于发送方引起的粘包现象用户可通过编程设置来避免TCP提供了强制数据立即传送的操作指令pushTCP程序收到该操作指令后就立即将本段数据发送出去而不必等待发送缓冲区满
2对于接收方引起的粘包则可通过优化程序设计、精简接收进程工作量、提高接收进程优先级等措施使其及时接收数据从而尽量避免出现粘包现象
3由接收方控制将一包数据按结构字段人为控制分多次接收然后合并通过这种手段来避免粘包。
## 为什么粘包需要处理?
不是所有的粘包现象都需要处理,若传输的数据为不带结构的连续流数据(如文件传输),则不必把粘连的包分开(简称分包)。但在实际工程应用中,传输的数据一般为带结构的数据,这时就需要做分包处理。分包一般难度较大,所以尽量避免粘包
# 三次握手相关问题
## 过程+状态改变
把**补充**里面的**第二个博客**的过程背下来。(有的地方需要参考第一个博客)
## 为什么三次,两次为什么不行?
### 第一种答案
两次握手只能保证单向连接是畅通的。只有经过第三次握手,才能确保双向都可以接收到对方的发送的 数据。两次握手接收方这里不能确定自己的的发送是正常的,发送方的接收是正常的。
**具体点:**
**三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。**
第一次握手Client 什么都不能确认Server 确认了对方发送正常,自己接收正常
第二次握手Client 确认了自己发送、接收正常对方发送、接收正常Server 确认了:对方发送正常,自己接收正常
第三次握手Client 确认了自己发送、接收正常对方发送、接收正常Server 确认了:自己发送、接收正常,对方发送、接收正常
所以三次握手就能确认双发收发功能都正常,缺一不可。
### 第二种答案
一句话主要防止已经失效的连接请求报文突然又传送到了服务器从而产生错误。如果使用的是两次握手建立连接假设有这样一种场景客户端发送了第一个请求连接并且没有丢失只是因为在网络结点中滞留的时间太长了由于TCP的客户端迟迟没有收到确认报文以为服务器没有收到此时重新向服务器发送这条报文此后客户端和服务器经过两次握手完成连接传输数据然后关闭连接。此时此前滞留的那一次请求连接网络通畅了到达了服务器这个报文本该是失效的但是两次握手的机制将会让客户端和服务器再次建立连接这将导致不必要的错误和资源的浪费。如果采用的是三次握手就算是那一次失效的报文传送过来了服务端接受到了那条失效报文并且回复了确认报文但是客户端不会再次发出确认。由于服务器收不到确认就知道客户端并没有请求连接。
## 如果已经建立了连接,但是客户端突然出现故障了怎么办?
<https://blog.csdn.net/qzcsu/article/details/72861891>
# 四次挥手相关问题
## 过程及状态改变
就是把**补充**里面的**第二个博客**的过程背下来。(有的地方需要参考第一个博客)
## 为什么四次挥手
因为只有在客户端和服务端都没有数据要发送的时候才能断开TCP。而客户端发出FIN报文时只能保证客户端没有数据发了服务端还有没有数据发客户端是不知道的。而服务端收到客户端的FIN报文后只能先回复客户端一个确认报文来告诉客户端我服务端已经收到你的FIN报文了但我服务端还有一些数据没发完等这些数据发完了服务端才能给客户端发FIN报文(所以不能一次性将确认报文和FIN报文发给客户端就是这里多出来了一次)。
## CLOSE-WAIT和TIME-WAIT存在的意义
- Close-wait存在的意义: 就是服务端还有数据要发送,这个时间内就是服务端发送完最后的数据
- Time-wait存在的意义:
- 第一这里同样是要考虑丢包的问题如果第四次挥手的报文丢失服务端没收到确认ack报文就会重发第三次挥手的报文这样报文一去一回最长时间就是2MSL所以需要等这么长时间来确认服务端确实已经收到了
- 第二防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后在这个2MSL时间中就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。
## 如何查看TIME-WAIT状态的链接数量(TODO)
## 为什么会TIME-WAIT过多解决方法是怎样的 (TODO)
## 为什么客户端最后还要等待2MSL
补充里的第二个博客
https://blog.csdn.net/qzcsu/article/details/72861891
# TCP
## 报文首部
<img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAyMC8xLzcvMTZmN2UwM2IxOWU2YzEzNA?x-oss-process=image/format,png">
**重要字段:**
1序号seq序号占32位用来标识从TCP源端向目的端发送的字节流发起方发送数据时对此进行标记。
2确认序号ack序号占32位只有ACK标志位为1时确认序号字段才有效ack=seq+1。
3标志位共6个即URG、ACK、PSH、RST、SYN、FIN等具体含义如下
ACK确认序号有效。
FIN释放一个连接。
PSH接收方应该尽快将这个报文交给应用层。
RST重置连接。
SYN发起一个新连接。
URG紧急指针urgent pointer有效。
**需要注意的是:**
不要将确认序号ack与标志位中的ACK搞混了。
确认方ack=发起方seq+1两端配对。
# 浏览器输入URL并回车的过程以及相关协议DNS查询过程。
## 过程
1、DNS域名解析得到IP地址
DNS解析流程:
> 参考https://blog.csdn.net/yanshuanche3765/article/details/82589210
>
> https://blog.csdn.net/u014465934/article/details/83241097
11. 浏览器先检查自身缓存中有没有被解析过的这个域名对应的ip地址(如果有解析结束。同时域名被缓存的时间也可通过TTL属性来设置。)
2在主机查询操作系统DNS缓存也就是hosts文件里配置的。
3如果浏览器和系统缓存都没有系统的 gethostname 函数就会像本地 DNS 服务器发送请求。而网络服务一般都会先经过路由器以及网络服务商(电信),所以会先查询路由器缓存,然后再查询 ISP 的 DNS 缓存。
4如果至此还没有命中域名才会真正的请求本地域名服务器LDNS来解析这个域名这台服务器一般在你的城市的某个角落距离你不会很远并且这台服务器的性能都很好一般都会缓存域名解析结果大约80%的域名解析到这里就完成了。
5如果LDNS仍然没有命中本地的DNS服务器向根域名服务器发送查询请求根域名服务器返回该域名的顶级级域名服务器。依次类推根域名服务器-顶级域名服务器-主域名服务器
2、解析出IP地址后根据IP地址和默认端口80和服务器建立连接发送http请求
3、服务器对浏览器的请求作出响应并把对应的html文本发送给浏览器
4、释放TCP连接四次挥手断开连接
6、浏览器解析该HTML文本并显示内容
## 用到的协议
- TCP:与服务器建立TCP连接
- IP: 建立TCP协议时需要发送数据发送数据在网络层使用IP协议
- OPSF: IP数据包在路由器之间路由选择使用OPSF协议
- ARP: 路由器在与服务器通信时需要将ip地址转换为MAC地址需要使用ARP协议
- HTTP:在TCP建立完成后使用HTTP协议访问网页
# HTTP1.0、1.1、2.0之间的区别
## TCP队头阻塞和HTTP队头阻塞
> http://www.mamicode.com/info-detail-2983775.html
**管道化请求的致命弱点**:
1、会造成队头阻塞前一个响应未及时返回后面的响应被阻塞
2、请求必须是幂等请求不能修改资源。因为意外中断时候客户端需要把未收到响应的请求重发非幂等请求会造成资源破坏。
3、由于这个原因目前大部分浏览器和Web服务器都关闭了管道化采用非管道化模式。无论是非管道化还是管道化都会造成队头阻塞(请求阻塞)。
**解决http队头阻塞的方法**
**1. 并发TCP连接**浏览器一个域名采用6-8个TCP连接并发HTTP请求
**2. 域名分片**多个域名可以建立更多的TCP连接从而提高HTTP请求的并发
**2. HTTP2方式**
http2使用一个域名单一TCP连接发送请求请求包被二进制分帧不同请求可以互相穿插避免了http层面的请求队头阻塞。
但是不能避免TCP层面的队头阻塞。
## http1.0
1.在HTTP/1.0中默认使用短连接。也就是说客户端和服务器每进行一次HTTP操作就建立一次连接任务结束就中断连接。
2.http队列头阻塞
请求队列的第一个请求因为服务器正忙(或请求格式问题等其他原因),导致后面的请求被阻塞
## http1.1
1、支持长链接
在request和response中的header中的connection是close或者Keep-Alive进行控制
一个TCP链接可以传送多个http请求和响应减少了TCP建立链接和关闭链接的消耗。
2、支持http管道(也就是流水线方式)
不使用管道的http请求在使用持久链接时必须严格满足先进先出的队列顺序FIFO即发送请求等待响应完成再发送客户端队列中的下一个请求。管道可以让我们把 FIFO 队列从客户端(请求队列)迁移到服务器(响应队列),即客户端可以并行,服务端串行。客户端可以不用等待前一个请求返回,发送请求,但服务器端必须顺序的返回客户端的请求响应结果。
但是http1.1任然无法解决http队头阻塞
**还有更细的就看补充里的第四个博客**
## http2.0
1.HTTP2.0最主要的特点是在不改动HTTP语义、方法、状态码、URI及首部字段的情况下大幅度提高了web性能。
**2.** **二进制传输**:大幅提高性能的一个原因就是: HTTP2.0中所有加强性能的核心是二进制传输在HTTP1.x中我们是通过文本的方式传输数据。基于文本的方式传输数据存在很多缺陷文本的表现形式有多样性因此要做到健壮性考虑的场景必然有很多但是二进制则不同只有0和1的组合因此选择了二进制传输实现方便且健壮。在HTTP2.0中引入了新的编码机制,所有传输的数据都会被分割,并采用二进制格式编码。
**3.** **多路复用**: HTTP2.0中有两个概念非常重要frame和流stream。帧是最小的数据单位每个帧会标识出该帧属于哪个流流是多个帧组成的数据流。所谓多路复用即在一个TCP连接中存在多个流即可以同时发送多个请求
对端可以通过帧中的表示知道该帧属于哪个请求。在客户端这些帧乱序发送到对端后再根据每个帧首部的流标识符重新组装【请求包被二进制分帧不同请求可以互相穿插】。通过该技术可以避免HTTP旧版本的队头阻塞问题极大提高传输性能
**4.** **Header压缩**
**5.** **服务器Push**: 在HTTP2.0中,服务端可以在客户端某个请求后,主动推送其他资源
**6.** **更安全**: HTTP2.0对tls的安全性做了近一步加强
# HTTP与HTTPS
## 区别
**1、端口**HTTP的URL由“http://”起始且默认使用端口80而HTTPS的URL由“https://”起始且默认使用端口443。
**2、安全性和资源消耗** HTTP协议运行在TCP之上所有传输的内容都是明文客户端和服务器端都无法验证对方的身份。HTTPS是运行在SSL/TLS之上的HTTP协议SSL/TLS 运行在TCP之上。所有传输的内容都经过加密加密采用对称加密但对称加密的密钥用服务器方的证书进行了非对称加密。所以说HTTP 安全性没有 HTTPS高但是 HTTPS 比HTTP耗费更多服务器资源
## HTTPS链接建立的过程
HTTPS在传输的过程中会涉及到三个密钥
- 服务器端的公钥和私钥,用来进行非对称加密
- 客户端生成的随机密钥,用来进行对称加密
一个HTTPS请求实际上包含了两次HTTP传输可以细分为8步。
1. 客户端向服务器发起HTTPS请求连接到服务器的443端口。
2. 服务器端有一个密钥对,即公钥和私钥,是用来进行非对称加密使用的,服务器端保存着私钥,不能将其泄露,公钥可以发送给任何人。
3. 服务器将自己的公钥发送给客户端。
4. 客户端收到服务器端的公钥之后会对公钥进行检查验证其合法性如果发现发现公钥有问题那么HTTPS传输就无法继续。【严格的说这里应该是验证服务器发送的数字证书的合法性关于客户端如何验证数字证书的合法性下文会进行说明。】如果公钥合格那么客户端会生成一个随机值这个随机值就是用于进行对称加密的密钥我们将该密钥称之为client key即客户端密钥这样在概念上和服务器端的密钥容易进行区分。然后用服务器的公钥对客户端密钥进行非对称加密这样客户端密钥就变成密文了至此HTTPS中的第一次HTTP请求结束。
5. 客户端会发起HTTPS中的第二个HTTP请求将加密之后的客户端密钥发送给服务器。
6. 服务器接收到客户端发来的密文之后,会用自己的私钥对其进行非对称解密,解密之后的明文就是客户端密钥,然后用客户端密钥对数据进行对称加密,这样数据就变成了密文。
7. 然后服务器将加密后的密文发送给客户端。
8. 客户端收到服务器发送来的密文用客户端密钥对其进行对称解密得到服务器发送的数据。这样HTTPS中的第二个HTTP请求结束整个HTTPS传输完成。
**详细就看补充-5博客**
## 了解对称加密算法和非对称加密算法不?
1.**对称加密**密钥只有一个加密解密为同一个密码且加解密速度快典型的对称加密算法有DES、AES等
**存在的问题:** 这种方式存在的最大问题就是密钥发送问题,即如何安全地将密钥发给对方,对称加密所使用的密钥我们可以通过非对称加密的方式发送出去。
**2.** **非对称加密**密钥成对出现且根据公钥无法推知私钥根据私钥也无法推知公钥加密解密使用不同密钥公钥加密需要私钥解密私钥加密需要公钥解密相对对称加密速度较慢典型的非对称加密算法有RSA、DSA等。
# HTTP请求有哪些。Post和get区别。
## 有哪些http请求
<https://www.runoob.com/http/http-methods.html>
## post和get的区别
1.GET提交的数据放在URL中POST数据放在Request body。(但这种情况仅限于浏览器发请求的场景)。这点意味着GET更不安全POST也不安全因为HTTP是明文传输抓包就能获取数据内容要想安全还得加密使用https
2.GET回退浏览器无害POST会再次提交请求GET方法回退后浏览器再缓存中拿结果POST每次都会创建新资源
3.GET提交的数据大小有限制是因为浏览器对URL的长度有限制GET本身没有限制POST没有
4.GET可以被保存为书签POST不可以。这一点也能感受到。这点可能没啥用
5.GET请求会被浏览器主动cache而POST不可缓存
6.对参数的数据类型GET只接受ASCII字符而POST没有限制。
7.GET会保存再浏览器历史记录中POST不会。这点也能感受到。
下面的就是深层次的
8.可以把 get 和 post 当作两个不同的行为,两者并没有什么本质区别,底层都是 TCP 连接
对于第1点的补充(如果需要举例子可以这样举)
> 其中的“<METHOD>"可以是GET也可以是POST或者其他的HTTP Method如PUT、DELETE、OPTION……。从协议本身看并没有什么限制说GET一定不能没有bodyPOST就一定不能把参放到<URL>的querystring上。因此其实可以更加自由的去利用格式。比如Elastic Search的_search api就用了带body的GET也可以自己开发接口让POST一半的参数放在url的querystring里另外一半放body里你甚至还可以让所有的参数都放Header里——可以做各种各样的定制只要请求的客户端和服务器端能够约定好
>
> 摘自---https://www.zhihu.com/question/28586791
# HTTP常见响应状态码从1xx到5xx都要说
<https://www.runoob.com/http/http-status-codes.html>
需要记住的(下面的应该足够了)
100, 101
200, 201, 202, 204
301, 302 , 304, 305
400, 401, 403, 404, 408
500, 502 ,504
# 重定向和转发区别
1、重定向是两次请求转发是一次请求。因此转发的速度要快于重定向
**重定向过程**:第一次客户端request一个网址,服务器响应并response回来告诉浏览器你应该去别一个网址。
2、重定向之后地址栏上的地址会发生变化变化成第二次请求的地址转发之后地址栏上的地址不会变化还是第一次请求的地址
3、转发是服务器行为重定向是客户端行为。
4、重定向时的网址可以是任何网址转发的网址必须是本站点的网址
# Session、Cookie和Token的主要区别
HTTP协议本身是无状态的。什么是无状态呢即服务器无法判断用户身份。
## 什么是cookie
cookie是由Web服务器保存在用户浏览器上的小文件key-value格式包含用户相关的信息。客户端向服务器发起请求如果服务器需要记录该用户状态就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie以此来辨认用户身份。
## 什么是session
session是依赖Cookie实现的。session是服务器端对象
session 是浏览器和服务器会话过程中服务器分配的一块储存空间。服务器默认为浏览器在cookie中设置 sessionid浏览器在向服务器请求过程中传输 cookie 包含 sessionid ,服务器根据 sessionid 获取出会话中存储的信息,然后确定会话的身份信息。
## cookie与session区别
存储位置与安全性cookie数据存放在客户端上安全性较差session数据放在服务器上安全性相对更高
存储空间单个cookie保存的数据不能超过4K很多浏览器都限制一个站点最多保存20个cookiesession无此限制
占用服务器资源session一定时间内保存在服务器上当访问增多占用服务器性能考虑到服务器性能方面应当使用cookie。
## 什么是Token
- Token的引入Token是在客户端频繁向服务端请求数据服务端频繁的去数据库查询用户名和密码并进行对比判断用户名和密码正确与否并作出相应提示在这样的背景下Token便应运而生。
- Token的定义Token是服务端生成的一串字符串以作客户端进行请求的一个令牌当第一次登录后服务器生成一个Token便将此Token返回给客户端以后客户端只需带上这个Token前来请求数据即可无需再次带上用户名和密码。
- 使用Token的目的Token的目的是为了减轻服务器的压力减少频繁的查询数据库使服务器更加健壮。
- Token 是在服务端产生的。如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端。前端可以在每次请求的时候带上 Token 证明自己的合法地位
- Token常用JWT实现原来需要客户端需要请求服务端验证session合法性现在只需要通过算法检验Token是否合法减少了查数据库或者访问服务器比对用户密码用户身份的消耗。也就是通过算法和密钥代替了访问数据库或服务器比对的过程
## session与token区别
- session机制存在服务器压力增大CSRF跨站伪造请求攻击扩展性不强等问题
- session存储在服务器端token存储在客户端
- token提供认证和授权功能作为身份认证token安全性比session好
- session这种会话存储方式方式只适用于客户端代码和服务端代码运行在同一台服务器上token适用于项目级的前后端分离前后端代码运行在不同的服务器下
# Reactor和Proactor区别
1.Reactor被动的等待指示事件的到来并做出反应它有一个等待的过程做什么都要先注册到监听事件集合中等待socket可读时再进行操作
2.Proactor直接调用异步读写操作调用完后放到到用户线程指定的缓存区接着通知用户线程直接使用即可。
3.Proactor是真正意义上的用于异步IO但是依赖操作系统对异步的支持。而Reactor用于同步IO
通俗语言:
reactor能收数据了你跟我说一声。
proactor: 这有十个字节数据,收好了跟我说一声。
> 想要理解这两设计模式,还是要真正的学习设计模式。
# 五种IO模型的区别
> 从下面这两个文章总结的:
>
> * https://blog.csdn.net/sehanlingfeng/article/details/78920423
> * http://www.tianshouzhi.com/api/tutorials/netty/221
>
> 下面总结的地方如果有不懂的,看上面的文章内容
>
> 下面这两篇文章看起来不错,不过还没认真看:
>
> * https://blog.csdn.net/ocean_fan/article/details/79622956
> * https://blog.csdn.net/ZWE7616175/article/details/80591587
在这里我们以一个网络IO来的read来举例它会涉及到两个东西一个是产生这个IO的进程另一个就是系统内核(kernel)。当一个read操作发生时它会经历两个阶段
**阶段1**等待数据准备
**阶段2**将数据从内核拷贝到进程中
## 阻塞IO
当用户进程进行recvfrom这个系统调用内核就开始了IO的第一个阶段等待数据准备。对于network io来说很多时候数据在一开始还没有到达比如还没有收到一个完整的UDP包这个时候**内核**就要等待足够的数据到来。而在用户进程这边,整 个进程会被阻塞。当**内核**一直等到数据准备好了,它就会将数据从**内核**中拷贝到用户内存,然后**内核**返回果,用户进程才解除 block的状态重新运行起来。**所以blocking IO的特点就是在IO执行的两个阶段都被block了。**
<img src="https://cdn.jsdelivr.net/gh/youthlql/lql_img/computer_network/summary/0003.png" width=80%>
<img src="http://images.cnitblog.com/blog/405877/201411/142330286789443.png" width=70%>
## 非阻塞IO
1. 当用户进程发出read操作时如果kernel中的数据还没有准备好那么它并不会block用户进程而是立刻返回一个error。
2. 从用户进程角度讲 它发起一个read操作后并不需要等待而是马上就得到了一个结果。用户进程判断结果是一个error时它就知道数据还没有准备好。用户线程需要不断地发起IO请求直到数据到达后才真正读取到数据继续执行。
3. 虽然用户线程每次发起IO请求后可以立即返回但是为了等到数据仍需要不断地轮询、重复请求消耗了大量的CPU的资源。一般很少直接使用这种模型而是在其他IO模型中使用非阻塞IO这一特性。
4. **所以,用户进程第一个阶段不是阻塞的,需要不断的主动询问内核数据好了没有;第二个阶段依然总是阻塞的。**
<img src="https://cdn.jsdelivr.net/gh/youthlql/lql_img/computer_network/summary/0004.png" width=80%>
<img src="http://images.cnitblog.com/blog/405877/201411/142332004602984.png" width=70%>
## 多路复用IO
1. IO多路复用模型是建立在内核提供的多路分离函数select基础之上的使用select函数可以避免同步非阻塞IO模型中轮询等待的问题。利用了新的select系统调用由内核来负责本来是请求进程该做的轮询操作
2. 它的基本原理就是select /epoll这个函数会不断的轮询所负责的所有socket当某个socket有数据到达了就通知用户进程正式发起read请求。
3. 从流程上来看使用select函数进行IO请求和同步阻塞模型没有太大的区别甚至还多了添加监视socket以及调用select函数的额外操作效率更差。但是使用select以后最大的优势是用户可以在一个线程内同时处理多个socket的IO请求。用户可以注册多个socket然后不断地调用select读取被激活的socket(也就是数据准备好了的socket)即可达到在同一个线程内同时处理多个IO请求的目的。而在同步阻塞模型中必须通过多线程的方式才能达到这个目的。
<img src="https://cdn.jsdelivr.net/gh/youthlql/lql_img/computer_network/summary/0005.png" width=80%>
### select函数的其它好处
> handle_events实现事件循环
>
> handle_event进行读/写等操作
1. 使用select函数的优点并不仅限于此。虽然上述方式允许单线程内处理多个IO请求但是每个IO请求的过程还是阻塞的在select函数上阻塞平均时间甚至比同步阻塞IO模型还要长。
2. 如果用户线程只注册自己感兴趣的socket或者IO请求然后去做自己的事情等到数据到来时再进行处理则可以提高CPU的利用率。
3. IO多路复用模型使用了Reactor设计模式实现了这一机制。
4. 通过Reactor的方式可以将用户线程轮询IO操作状态的工作统一交给handle_events事件循环进行处理。用户线程注册事件处理器之后可以继续执行做其他的工作异步而Reactor线程负责调用内核的select函数检查socket状态。当有socket被激活时(就是数据准备好的时候)则通知相应的用户线程或执行用户线程的回调函数执行handle_event进行数据读取、处理的工作。
5. 由于select函数是阻塞的因此多路IO复用模型也被称为异步阻塞IO模型。注意这里的所说的阻塞是指select函数执行时线程被阻塞而不是指socket。(一般在使用IO多路复用模型时socket都是设置为NONBLOCK的不过这并不会产生影响因为用户发起IO请求时数据已经到达了用户线程一定不会被阻塞。)
<img src="http://images.cnitblog.com/blog/405877/201411/142333254136604.png" width=80%>
## 信号驱动IO
1. 在信号驱动IO模型中当用户线程发起一个IO请求操作会给对应的socket注册一个信号函数然后用户线程会继续执行当内核数据就绪时会发送一个信号给用户线程用户线程接收到信号之后便在信号函数中调用IO读写操作来进行实际的IO请求操作。
2. 这个一般用于UDP中对TCP套接口几乎是没用的原因是该信号产生得过于频繁并且该信号的出现并没有告诉我们发生了什么事情
3. 信号驱动IO放佛很像异步IO它的第一阶段不是阻塞的。但是很遗憾它的数据拷贝阶段(第二阶段),任然是阻塞的。
<img src="https://cdn.jsdelivr.net/gh/youthlql/lql_img/computer_network/summary/0006.png" width=80%>
## 异步IO
1. 真正”的异步IO需要操作系统更强的支持。在IO多路复用模型中由用户线程自行读取数据、处理数据。
2. 而在异步IO模型中用户进程发起read操作之后立刻就可以开始去做其它的事。
3. 而另一方面,从**内核**的角度,当它受到一个异步读之后,首先它会立刻返回,所以不会对用户进程产生任何阻塞。然后,内核会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都 完成之后,**内核**会给用户进程发送一个信号告诉它read操作完成了用户线程直接使用即可。 在这整个过程中,进程完全没有被阻塞。
4. 异步IO模型使用了Proactor设计模式实现了这一机制。**(具体怎么搞得,看上面的文章链接)**
<img src="https://cdn.jsdelivr.net/gh/youthlql/lql_img/computer_network/summary/0007.png" width=80%>
<img src="http://images.cnitblog.com/blog/405877/201411/142333511475767.png">
# select、poll、epoll的区别
> select, poll, epoll 都是I/O多路复用的具体的实现之所以有这三个存在其实是他们出现是有先后顺序的。
>
> * https://blog.csdn.net/nanxiaotao/article/details/90612404
> * https://www.cnblogs.com/aspirant/p/9166944.html
> * https://www.zhihu.com/question/32163005
## select
1. 它仅仅知道了有I/O事件发生了却并不知道是哪那几个流可能有一个多个甚至全部只能无差别轮询所有流找出能读出数据或者写入数据的流对他们进行操作。所以**select具有O(n)的无差别轮询复杂度**,同时处理的流越多,无差别轮询时间就越长。
2. 单个进程可监视的fd_set(监听的端口个数)数量被限制32位机默认是1024个64位机默认是2048。
## poll
poll本质上和select没有区别采用**链表**的方式替换原有fd_set数据结构,而使其**没有连接数的限制**。
## epoll
1. epoll可以理解为event poll不同于忙轮询和无差别轮询epoll会把哪个流发生了怎样的I/O事件通知我们。所以我们说epoll实际上是事件驱动每个事件关联上fd此时我们对这些流的操作都是有意义的。复杂度降低到了O(1)
2. 效率提升不是轮询的方式不会随着FD数目的增加效率下降。只有活跃可用的FD才会调用callback函数。即Epoll最大的优点就在于它只管你“活跃”的连接而跟连接总数无关因此在实际的网络环境中Epoll的效率就会远远高于select和poll。
3. epoll通过内核和用户空间共享一块内存来实现的。select和poll都是内核需要将消息传递到用户空间都需要内核拷贝动作
4. epoll有EPOLLLT和EPOLLET两种触发模式。(**暂时不去记,有个印象,大致是什么样就可以**)
# IO疑难点
https://blog.csdn.net/m0_38109046/article/details/89449305
https://www.zhihu.com/question/19732473
[漫画讲IO](https://mp.weixin.qq.com/s?__biz=Mzg3MjA4MTExMw==&mid=2247484746&idx=1&sn=c0a7f9129d780786cabfcac0a8aa6bb7&source=41&scene=21#wechat_redirect)