目录
HTTP和HTTPS的区别
HTTP1.0/1.1/2.0的区别
无状态协议
GET和POST区别
UDP和TCP的区别
三次握手和四次挥手
HTTP常见的请求头
地址栏输入URL发生了什么
常见状态码
TCP保证有效传输
重传机制
滑动窗口
流量控制
拥塞控制
HTTP(Hypertext Transfer Protocol secure)是一种超文本传输协议,主要内容分为三个部分,超文本、传输、协议。
HTTPS比HTTP多了secure概念,Hypertext Transfer Protocol Secure。 在HTTP的基础上增加了SSL/TLS协议组合而成,HTTPS就是批了一层SSL的HTTP。
1、 客户端发出请求
首先,客户端(通常是浏览器)先向服务器发出加密通信的请求,这被叫做ClientHello请求。
2、服务器回应
服务器收到客户端请求后,向客户端发出回应,这叫做SeverHello。生成随机数1,返回数字证书和公钥
3、客户端回应
客户端收到服务器回应以后,首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。然后使用公钥加密生成一个随机数2,返回给服务器
4、服务器的最后回应
服务器用私钥解密随机数2,生成随机数3。然后用三个随机数生成“对话密钥”,并返回给客户端。
(1) SSLclient通过Client Hello消息将它支持的SSL版本号、加密算法、密钥交换算法、MAC算法等信息发送给SSLserver。
(2) SSLserver确定本次通信采用的SSL版本号和加密套件,并通过Server Hello消息通知给SSLclient。假设SSLserver同意SSLclient在以后的通信中重用本次会话,则SSLserver会为本次会话分配会话ID。并通过Server Hello消息发送给SSLclient。
(3) SSLserver将携带自己公钥信息的数字证书通过Certificate消息发送给SSLclient。
(4) SSLserver发送Server Hello Done消息。通知SSLclient版本号和加密套件协商结束。开始进行密钥交换。
(5) SSLclient验证SSLserver的证书合法后,利用证书中的公钥加密SSLclient随机生成的premaster secret,并通过Client Key Exchange消息发送给SSLserver。
(6) SSLclient发送Change Cipher Spec消息,通知SSLserver兴许报文将采用协商好的密钥和加密套件进行加密和MAC计算。
(7) SSLclient计算已交互的握手消息(除Change Cipher Spec消息外全部已交互的消息)的Hash值,利用协商好的密钥和加密套件处理Hash值(计算并加入MAC值、加密等),并通过Finished消息发送给SSLserver。SSLserver利用相同的方法计算已交互的握手消息的Hash值,并与Finished消息的解密结果比较,假设二者相同,且MAC值验证成功,则证明密钥和加密套件协商成功。
(8) 相同地。SSLserver发送Change Cipher Spec消息,通知SSLclient兴许报文将采用协商好的密钥和加密套件进行加密和MAC计算。
(9) SSLserver计算已交互的握手消息的Hash值,利用协商好的密钥和加密套件处理Hash值(计算并加入MAC值、加密等),并通过Finished消息发送给SSLclient。SSLclient利用相同的方法计算已交互的握手消息的Hash值,并与Finished消息的解密结果比较,假设二者相同。且MAC值验证成功。则证明密钥和加密套件协商成功。
SSLclient接收到SSLserver发送的Finished消息后。假设解密成功,则能够推断SSLserver是数字证书的拥有者,即SSLserver身份验证成功,由于仅仅有拥有私钥的SSLserver从Client Key Exchange消息中解密得到premaster secret,从而间接地实现了SSLclient对SSLserver的身份验证。
说明:
* Change Cipher Spec消息属于SSLpassword变化协议,其它握手过程交互的消息均属于SSL握手协议,统称为SSL握手消息。
* 计算Hash值。指的是利用Hash算法(MD5或SHA)将随意长度的数据转换为固定长度的数据。
无状态协议就是指浏览器对于事务的处理没有记忆能力。HTTP就是一种无状态的协议,他对用户的操作没有记忆能力。
为什么我在网站输入一次用户名和密码后,下次登录可以不用重新输入呢?
这是基于cookie机制(TCP快速建立连接原理),它让浏览器有了记忆能力。
客户端向服务端发送请求的时候,服务端会给你发送一个认证信息,服务器第一次接收到请求的时候,开辟一块session空间,同时生成一个sessionid,并通过响应头的Set-Cookie,返回给客户端。客户端收到响应后,设置自己的Cookie,以后请求就可以带着Cookie访问,浏览器通过拿到cookie生成sessionid就可以鉴定客户端的身份。所以浏览器就有了记忆能力。
JWT-Token机制
JWT和Cookie不同,JWT是保存在客户端的信息,它适用于单点登录的情况。
Token机制
1. 客户端使用用户名跟密码请求登录
2. 服务端收到请求,去验证用户名与密码
3. 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
4. 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里
5. 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
6. 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向
客户端返回请求的数据
HTTP包含许多方法,GET和POST是HTTP中最常用的两个方法。
TCP和UDP都是位于计算机网络中的运输层,它们负责传输应用层产生的数据。
UDP不需要所谓的握手操作,从而加快了通信速度,允许网络上的其他主机在接收方同意通信之前进行数据传输。
在传输之前会进行三次握手确认连接
三次握手和四次挥手,分别对应了TCP的连接和释放过程。
先了解几个概念
第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
小明 - 客户端 小红 - 服务端
还是可以用上面那个通话的例子来进行描述
为什么TIME_WAIT需要经过2MSL才能返回到CLOSE状态?
虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
如果已经建立了连接,客户端出现了故障怎么办?
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
为什么是三次握手,不是二次或者四次握手?
TCP是全双工的,即客户端在给服务器端发送信息的同时,服务器端也可以给客户端发送信息。所以就需要确定,客户端和服务端需要确认自己和对方都具有良好的收发能力。
第一次握手:A对B 说,你可以听到我说话吗?
第二次握手:B回A的消息,我能听到你说话,你能听到我说话吗?这个阶段B知道A的发送能力,自己的接收能力。
第三次握手:A收到B的信息,说可以听到你说话。A知道自己的接收和发送能力都是好的,B的接收和发送能力是正常的。B此时知道了自己的发送能力正常,A的接收能力正常。
HTTP标头会分为四种,分别是通用标头、实体标头、请求标头、响应标头。
通用标头
Date: 日期时间
Cache-Control:缓存控制
Connection:持久性连接/非持久性连接
实体标头
实体标头是描述消息正文内容的HTTP标头。实体标头用于HTTP请求和响应中
Content-Length:实体主题的大小,以字节为单位,发送到接收方
Content-Language:描述了客户端或者服务端能够接受的语言
Content-Encoding:压缩媒体类型,采用何种编码
请求标头
Host:指明了服务器的域名,以及可选的端口号(默认为80)
Refer:告诉服务器是从哪个页面链接过来的
If-Modified-Since:如果在Last-Modified之后更新了服务器资源,那么服务器会响应200,如果Last-Modified之后没有更新过资源,则返回304.
Accept: 接受请求HTTP表土会告知客户端其能够理解的MIME类型
Accept-Charset: 服务器处理表单数据接受的字符集
Accept-Language:服务器能够处理的自然语言集
响应标头
keep-alive:非持续连接的存活时间,可以进行指定
server:服务器标头包含有关原始服务器用来处理请求的软件的信息
Set-Cookie:用于服务器向客户端发送sessionID
Transfer-Encoding:首部字段Transfer-Encoding规定了传输报文主题时采用的编码方式
1xx
1xx 类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。
2xx
2xx 类状态码表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。
「200 OK」是最常见的成功状态码,表示一切正常。如果是非 HEAD 请求,服务器返回的响应头都会有 body 数据。
「204 No Content」也是常见的成功状态码,与 200 OK 基本相同,但响应头没有 body 数据。
「206 Partial Content」是应用于 HTTP 分块下载或断电续传,表示响应返回的 body 数据并不是资源的全部,而是其中的一部分,也是服务器处理成功的状态。
3xx
3xx 类状态码表示客户端请求的资源发送了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。
「301 Moved Permanently」表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问。
「302 Moved Permanently」表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。
301 和 302 都会在响应头里使用字段 Location,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。
「304 Not Modified」不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,用于缓存控制。
4xx
4xx 类状态码表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。
「400 Bad Request」表示客户端请求的报文有错误,但只是个笼统的错误。
「403 Forbidden」表示服务器禁止访问资源,并不是客户端的请求出错。
「404 Not Found」表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。
5xx
5xx 类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。
「500 Internal Server Error」与 400 类型,是个笼统通用的错误码,服务器发生了什么错误,我们并不知道。
「501 Not Implemented」表示客户端请求的功能还不支持,类似“即将开业,敬请期待”的意思。
「502 Bad Gateway」通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。
「503 Service Unavailable」表示服务器当前很忙,暂时无法响应服务器,类似“网络服务正忙,请稍后重试”的意思。
TCP如果在传输过程中,数据丢失了怎么办?针对TCP丢包情况,会用重传机制解决。常见的重传机制:
超时重传
发送数据的时候,设定一个定时器,如果超过指定的时间没有接收到对方的ACK确认应答报文,就会重发该数据。
两种情况下回发送超时重传:
超时重传时间RTO:
超时重传时间RTO的值应该略大于报文往返RTT的值。(RTT包的往返时间)。RTT的值是多次测试得到的一个靠谱的值。
超时重发的数据,再次超时的时候,又需要重传的时候,TCP策略是超时间隔加倍。两次超时,就说明网络环境差,不宜频繁反复发送。
超时重传的存在的问题是,超时周期可能相对较长。是不是有可以有更快的方式呢?【快速重传】
快速重传
TCP还有另外一种快速重传机制,不以时间为驱动,而是以数据驱动重传。
在上图,发送方发出了 1,2,3,4,5 份数据:
所以,快速重传的工作方式是当收到三个相同的 ACK 报文时,会在定时器过期之前,重传丢失的报文段。
快速重传机制只解决了一个问题,就是超时时间的问题,但是它依然面临着另外一个问题。就是重传的时候,是重传之前的一个,还是重传所有的问题。
比如对于上面的例子,是重传 Seq2 呢?还是重传 Seq2、Seq3、Seq4、Seq5 呢?因为发送端并不清楚这连续的三个 Ack 2 是谁传回来的。
SACK
这种方式需要在 TCP 头部「选项」字段里加一个 SACK 的东西,它可以将缓存的地图发送给发送方,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据。
D-SACK
Duplicate SACK 又称 D-SACK,其主要使用了 SACK 来告诉「发送方」有哪些数据被重复接收了。
引入滑动窗口的原因
TCP每发送一个数据包,都要进行一次确认应答,当上一个数据包接受到了应答,再发送下一个。
这个模式就有点像我和你面对面聊天,你一句我一句。但这种方式的缺点是效率比较低的。
如果你说完一句话,我在处理其他事情,没有及时回复你,那你不是要干等着我做完其他事情后,我回复你,你才能说下一句话,很显然这不现实。
所以,这样的传输方式有一个缺点:数据包的往返时间越长,通信的效率就越低。
为解决这个问题,TCP 引入了窗口这个概念。即使在往返时间较长的情况下,它也不会降低网络通信的效率。
那么有了窗口,就可以指定窗口大小,窗口大小就是指无需等待确认应答,而可以继续发送数据的最大值。
窗口的实现实际上是操作系统开辟的一个缓存空间,发送方主机在等到确认应答返回之前,必须在缓冲区中保留已发送的数据。如果按期收到确认应答,此时数据就可以从缓存区清除。
图中的 ACK 600 确认应答报文丢失,也没关系,因为可以通话下一个确认应答进行确认,只要发送方收到了 ACK 700 确认应答,就意味着 700 之前的所有数据「接收方」都收到了。这个模式就叫累计确认或者累计应答。
窗口大小由谁决定的?
TCP 头里有一个字段叫 Window,也就是窗口大小。
这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。
所以,通常窗口的大小是由接收方的决定的。
发送方发送的数据大小不能超过接收方的窗口大小,否则接收方就无法正常接收到数据。
发送方不能无脑的发数据给接收方,要考虑接收方处理能力。
如果一直无脑的发数据给对方,但对方处理不过来,那么就会导致触发重发机制,从而导致网络流量的无端的浪费。
为了解决这种现象发生,TCP 提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是所谓的流量控制。
为什么要有拥塞控制?
流量控制是避免「发送方」的数据填满「接收方」的缓存,但是并不知道网络的中发生了什么。
一般来说,计算机网络都处在一个共享的环境。因此也有可能会因为其他主机之间的通信使得网络拥堵。
在网络出现拥堵时,如果继续发送大量数据包,可能会导致数据包时延、丢失等,这时 TCP 就会重传数据,但是一重传就会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,这个情况就会进入恶性循环被不断地放大….
所以,TCP 不能忽略网络上发生的事,它被设计成一个无私的协议,当网络发送拥塞时,TCP 会自我牺牲,降低发送的数据量。
于是,就有了拥塞控制,控制的目的就是避免「发送方」的数据填满整个网络。
为了在「发送方」调节所要发送数据的量,定义了一个叫做「拥塞窗口」的概念。
什么是拥塞窗口?
cwnd是发送方维护的一个 的状态变量,它会根据网络的拥塞程度动态变化的。
拥塞窗口 cwnd 变化的规则:
发送窗口swnd和接收窗口rwnd是约等于的关系,在引入拥塞窗口的概念后,此时发送窗口的值是swnd=min(cwnd, rwnd),也就是拥塞窗口和接收窗口的最小值。
怎么知道当前网络是否出现了拥塞呢?
其实只要「发送方」没有在规定时间内接收到 ACK 应答报文,也就是发生了超时重传,就会认为网络出现了用拥塞。
拥塞控制有哪些控制算法?
慢启动
连接建立完成后,一开始初始化cwnd=1,以后每次接收到一个ACK,拥塞窗口cwnd的大小就会*2。此时拥塞窗口处于指数增长
慢启动有个启动门限ssthresh状态变量。
当
拥塞避免算法
当拥塞窗口cwnd超过慢启动门限ssthresh时,就会进入拥塞避免算法:每当收到一个ACK时,cwnd增加1/cwnd。此时拥塞窗口处于线性增长。
一直这么增长着,网络就会慢慢进入拥塞的状况,于是就会出现丢包现象,这时就需要对丢失的数据包进行重传。此时触发了重传机制,也就进入了[拥塞发生算法]
拥塞发生
网络出现拥塞,也就是会发生数据包重传,重传机制主要由两种:
发生超时重传时的拥塞发生算法
发生快速重传的拥塞发生算法
快速恢复
快速重传和快速恢复算法一般同时使用,快速恢复算法认为你还能收到3个重复ACK,证明网络没有那么糟。
进入快速恢复之前,cwnd和ssthresh已被更新了。
进入快速恢复算法如下: