文章目录
1.网络协议层次
TCP/IP层次对应协议
- 应用层:HTTP,DNS(域名解析协议),FTP(文件传输协议)
- 传输层:UDP,TCP
- 网络层:IP(网际协议),ICMP(互联网控制报文协议),IGMP(互联网组管理协议),RIP
2.TCP和UDP区别
UDP:对网络通讯质量要求不高时,要求网络通讯速度要快的场景
- 无连接,发送数据之前不需要建立连接。
- 尽最大努力交付,不保证可靠交付,不使用拥塞控制。
- 面向报文,适合多媒体通信。
- 支持一对一,一对多,多对一,多对多的交互通信。
- 首部开销小,8个字节。
TCP:当对网络通讯质量有要求时,比如HTTP、HTTPS、FTP等传输文件的协议, POP3、SMTP等邮件传输的协议
- 面向连接。
- 每一条TCP有且只有两个端点,为一对一关系。
- 提供可靠交付。
- 全双工通信,全双工为即可传输又可接收。
- 面向字节流。
**常问问题:**实时直播、游戏用tcp还是udp好
**回:**直播udp,速度快!,会丢包但是不卡顿,实时性好(目前tcp主流,因为tcp库多,开发周期短)
游戏tcp好,安全可靠性高,第三方库多
3.TCP为什么可靠
- 乱序重排
- 应答确认
- 报文重传
- 流量控制(接收方受不了)
- 拥塞控制(网路受不了)
1.乱序重排、应答确认
都跟序号有关。由于网络或“多线程”等因素,接收方收到的数据段很可能是乱序的,不过,因为每个TCP封装都有序号,接收方重组起来非常容易。
发送方每发送一个数据段,如果都等着收到接收方的确认后再发下一个,这效率太低了。我们在解释Acknowledgement Number确认号时,曾举过一个栗子,发送方的数据有1000字节,接收方收到后的确认号填写1001,是告诉发送方前面的都收到了,下次从序号1001开始发。那么,如果发送方发送了多个数据段,共5000字节,接收方只需发一个确认号为5001的报文,是不是就可以呢?
没错,TCP就是这么干的!这就大大提高了效率。至于一次收多少字节再发确认,由接收方window决定。
2.报文重传
一种是超时重传,发送方收不到确认的时候用。我们都知道网速并不是稳定的,传输时的每个报文的延时也不一样。TCP会根据报文的往返时间(RTT)自动调整超时重传时间(RTO)。发送方每发一个报文段都会开始计时,如果时间超过RTO还没收到这个报文段的确认,就重传该报文段。
另一种方法是快速重传,发送的数据在路上丢失的时候用。
我们看下图:
接收方收到序号1后,回复确认号2,希望下次收到序号2的报文段,但却乱序收到比序号2大的3、4、5报文段,于是连续发出确认号为2的报文段。如果发送方连续三次收到重复的确认号,立即重发该报文段,而不管是否超时。
3.流量控制(滑动窗口解决)
首先要明白一点,应用程序不论发送还是接收数据,都会先把数据放入缓冲区,再从缓冲区中发出或读取数据。就像秘书,先把事情整理归纳好,再一次性向你汇报。
这个缓冲区大小,反映了应用程序一次能处理数据的能力。如果接收方应用程序处理速度比发送方的发送速度慢,就会造成接收方缓冲区“溢出”。实际上,发送方发送速度和接收方处理速度很难一致。
这就需要window来调整了。
TCP在三次握手建立连接时,会协商双方缓冲区window大小。如果因为接收方处理速度较慢,接收方会通过window告知发送方,实现动态调整,避免“溢出”。
TCP滑动窗口分为接受窗口,发送窗口
滑动窗口协议是传输层进行流控的一种措施,接收方通过通告发送方自己的窗口大小,从而控制发送方的发送速度,从而达到防止发送方发送速度过快而导致自己被淹没的目的。
对ACK的再认识,ack通常被理解为收到数据后给出的一个确认ACK,ACK包含两个非常重要的信息:
**一是期望接收到的下一字节的序号n,该n代表接收方已经接收到了前n-1字节数据,此时如果接收方收到第n+1字节数据而不是第n字节数据,****接收方是不会发送序号为n+2的ACK的。**举个例子,假如接收端收到1-1024字节,它会发送一个确认号为1025的ACK,但是接下来收到的是2049-3072,它是不会发送确认号为3072的ACK,而依旧发送1025的ACK。二是当前的窗口大小m,如此发送方在接收到ACK包含的这两个数据后就可以计算出还可以发送多少字节的数据给对方,假定当前发送方已发送到第x字节,则可以发送的字节数就是y=m-(x-n).这就是滑动窗口控制流量的基本原理
重点:发送方根据收到ACK当中的期望收到的下一个字节的序号n以及窗口m,还有当前已经发送的字节序号x,算出还可以发送的字节数。
4.拥塞控制(拥塞窗口)
慢开始
拥塞避免
快速重传
快速恢复
swnd发送窗口 = min(cwnd拥塞窗口, rwnd接收窗口)
(1)慢开始
假设当前发送方拥塞窗口cwnd的值为1,而发送窗口swnd等于拥塞窗口cwnd,因此发送方当前只能发送一个数据报文段(拥塞窗口cwnd的值是几,就能发送几个数据报文段),接收方收到该数据报文段后,给发送方回复一个确认报文段,发送方收到该确认报文后,将拥塞窗口的值变为2。即收到多少确认报文就增加多少。所以拥塞窗口是以指数型增长的(1,2,4,8…)。一直到cwnd等于ssthresh阈值时启动拥塞控制算法。如下图,慢开始增长速度并不慢,只是开始时向网络注入数据报文较少。
(2)拥塞避免
进入拥塞避免阶段时,cwnd每次只能加1。当出现报文丢失时,丢失的报文的重传计时器超时后会被判断出现拥塞,此时需要更改cwnd和ssthresh。
出现拥塞:
1、ssthresh更新为出现拥塞时cwnd数值的一半;
2、cwnd赋值为1;
3、重新执行慢开始算法。
如下图所示,初始ssthresh为16,当cwnd小于ssthresh成指数型增长,当cwnd > ssthresh时,cwnd逐次增加1。当其值为24时,出现丢包,此时判断为拥塞,将ssthresh调整为出现拥塞时的一般,即12。之后cwnd赋值为1,重新执行慢开始算法。由下图仍可见,拥塞避免并不是完全避免拥塞,而是将拥塞窗口的增长变为线性的,使网络不容易出现拥塞。
以上的两个算法存在不足之处,当个别报文在网络中丢失时,可能实际上网络并未发生拥塞。这将导致发送端超时重传,并误以为网络发送拥塞。由于每次拥塞控制都会将cwnd设置为1,这严重降低了传输效率。由此,新增了快速重传算法和快速恢复算法。
(3)快重传
(4)快恢复(区别丢失个别报文还是网络拥塞,防止误判)
如下,发送端连续接收端三个重复确认报文后可以确认只是丢失了个别报文(确认报文可以传回,网络没有拥塞),此时不需要启动慢开始算法。此时将ssthresh和cwnd赋值为此时的cwnd的一半,然后执行拥塞避免算法。具体机制如下图所示。
当然也有的快速回复算法,将cwnd的值增大3,即cwnd = ssthresh + 3(ssthresh为连续三次受到确认号时的cwnd值的一半)。因为接收端缓存中已经存在了三个数据报文,这三个报文不会再占用网络资源,所以拥塞窗口可以适当增大。这么做也是为了尽可能提高吞吐量。
4.在浏览器中输入URL后,执行的全部过程。(一次完整的http请求过程)
整个流程如下:
域名解析
发起TCP的3次握手
建立TCP连接后发起http请求
服务器响应http请求
浏览器解析html代码,并请求html代码中的资源(如js、css、图片等)
断开TCP连接
浏览器对页面进行渲染呈现给用户
(1)域名解析
-
例如,要查询www.baidu.com的IP地址(DNS解析url):
-
浏览器搜索自己的DNS缓存(维护一张域名与IP地址的对应表)
-
若没有,则搜索操作系统中的DNS缓存(维护一张域名与IP地址的对应表)
-
若没有,则搜索操作系统的hosts文件(Windows环境下,维护一张域名与IP地址的对应表,位置一般在 C:\Windows\System32\drivers\etc\hosts)
-
若没有,则操作系统将域名发送至 本地域名服务器- -(递归查询方式),本地域名服务器 查询自己的DNS缓存,查找成功则返回结果,否则,(以下是迭代查询方式)
-
4.1 本地域名服务器 向根域名服务器(其虽然没有每个域名的具体信息,但存储了负责每个域,如com、net、org等的解析的顶级域名服务器的地址)发起请求,此处,根域名服务器返回com域的顶级域名服务器的地址
-
4.2 本地域名服务器 向com域的顶级域名服务器发起请求,返回baidu.com权限域名服务器(权限域名服务器,用来保存该区中的所有主机域名到IP地址的映射)地址
-
4.3 本地域名服务器 向baidu.com权限域名服务器发起请求,得到www.baidu.com的IP地址
-
本地域名服务器 将得到的IP地址返回给操作系统,同时自己也将IP地址缓存起来
-
操作系统将 IP 地址返回给浏览器,同时自己也将IP地址缓存起来
-
至此,浏览器已经得到了域名对应的IP地址
(2)三次握手
三次握手的情况可以看我的博客https://blog.csdn.net/qq_21993785/article/details/80735776
(3)建立TCP连接后发起http请求
讲一下HTTP的浏览器缓存机制看我的博客:https://blog.csdn.net/qq_21993785/article/details/81188624。使用Post还是Get。
(4)服务器收到请求并响应HTTP请求
- 负载均衡:网站可能会有负载均衡设备来平均分配所有用户的请求。即对工作任务进行平衡,分摊到多个操作单元上执行,如图片服务器,应用服务器等。
- 请求处理阅读请求及它的参数和 cookies
(5)浏览器解析html代码,并请求html代码中的资源(如js、css图片等)
看是否是长连接。来决定是不是断开TCP连接
(6)断开TCP连接(四次挥手)
(7)浏览器对页面进行渲染呈现给用户
5.TCP第三次握手原因
简述三次握手
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手
简述三次握手
关于第三次握手(防止A以前遗失在网络中的请求和B直接建立连接,死锁B):
为什么A还要在发送一次确认呢?这主要原因是为了防止已经失效的连接请求报文又突然传到了B,因而产生错误。
所谓“已失效的连接请求报文段”是这样产生的。考虑一种可能情况,A发起连接请求,但是因为连接请求报文丢失而未收到确认。于是A再重新传一次请求。后来收到了确认,建立连接。数据传输完毕后,就释放了连接。A工发送了两个连接请求报文段,其中第一个丢失,第二个到达了B。没有“已失效的连接请求报文段”。
现假定一种异常情况,A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,以致延误到连接释放后的某个时间到达B。本来这是一个早已经失效的报文段,但是B收到此失效的连接请求报文段后,就误认为是A又发出一次连接新的请求。于是就向A发出来确认报文段,同一建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了。
由于A并没有发出建立连接的请求,因此不会理睬B的确认,也不会向B发送数据。但B却以为新的运输连接已经建立了,并一直等待A发送数据,B的许多资源就白白浪费了!!!
采用三次握手的方法可以防止上述现象发生。例如刚刚的情况,A不会向B的确认而发出确认。B由于收不到确认,就知道A并没有要求建 立连接。
6.tcp四次挥手原因
-
第二次挥手和第三次挥手不能合并原因:第二次挥手是因为服务器B还没传完,先回应一声,然后接着传,传完挥手第三次
-
为什么还要挥手第四次:因为带三次挥手有可能丢失,客户端A就会一直等待,所以需要第四次挥手确认。
-
第四次挥手后等2MSL原因:第四次挥手有可能丢失,服务器B收不到会重新请求,所以客户端A等一会就是为了怕第四次挥手失败。如果第四次挥手失败,B没收到且A如果没等,A就接收不到B的重新请求,B就永远收不到第四次挥手,处于死锁。A等了2MSL,
还没收到B重新请求,就判定B接受到了第四次挥手,此时断开TCP链接。
7.HTTP 与 HTTPS的区别
HTTP:
1.HTTP协议目的是规定客户端和服务端数据传输的格式和数据交互行为,并不负责数据传输的细节。底层是基于TCP实现的。现在使用的版本当中是默认持久连接的,也就是多次HTTP请求使用一个TCP连接。
2.HTTP协议是无状态的,每次HTTP请求都是独立的,任何两个请求之间没有什么必然的联系。但是在实际应用当中并不是完全这样的,引入了Cookie和Session机制来关联请求。
3.方法:get,post,delete,put。。。
区别:
- HTTPS 协议需要到 CA(Certificate Authority,证书颁发机构)申请证书,一般免费证书较少,因而需要一定费用。
- HTTP 是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 TLS 加密传输协议。
- HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
- HTTP 的连接很简单,是无状态的。HTTPS 协议是由 TLS+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。(无状态的意思是其数据包的发送、传输和接收都是相互独立的。无连接的意思是指通信双方都不长久的维持对方的任何信息。)
HTTPS详解:
步骤
- 用户在浏览器发起HTTPS请求( 如https://www.mogu.com ),默认使用服务端的443端口进行连接;
- HTTPS需要使用一套CA数字证书,证书内会附带一个公钥Pub,而与之对应的私钥Private保留在服务端不公开;
- 服务端收到请求,返回配置好的包含公钥Pub的证书给客户端;
- 客户端收到证书,校验合法性,主要包括是否在有效期内、证书的域名与请求的域名是否匹配,上一级证书是否有效(递归判断,直到判断到系统内置或浏览器配置好的根证书),如果不通过,则显示HTTPS警告信息,如果通过则继续;
- 客户端生成一个用于对称加密的随机Key,并用证书内的公钥Pub进行加密,发送给服务端;
- 服务端收到随机Key的密文,使用与公钥Pub配对的私钥Private进行解密,得到客户端真正想发送的随机Key;
- 服务端使用客户端发送过来的随机Key对要传输的HTTP数据进行对称加密,将密文返回客户端;
- 客户端使用随机Key对称解密密文,得到HTTP数据明文;
- 后续HTTPS请求使用之前交换好的随机Key进行对称加解密。
8.get post 区别
- get用于请求服务器返回资源,post一般用于表单的提交。
- get方法请求参数会拼接在URL上不安全。post方法请求参数放在请求体body中。
- get请求URL有长度限制,post对长度无要求。
- get请求会被浏览器主动cache,post不会,除非手动设置。
- get请求在浏览器反复的 回退/前进 操作是无害的,而post操作会再次提交表单请求。
- get请求在发送过程中会产生一个TCP数据包,post在发送过程中会产生两个TCP数据包。 对于get请求,浏览器会把http header和data一并发送出去,服务器响应200;而对于post,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok。
9.cookie和session区别
-
Cookie存放在客户端浏览器中 Session存放在服务器中。
-
cookie的大小受限制,单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。 session的大小一般不受限制。
-
工作原理:
-
服务器第一次接收到请求时,开辟了一块Session空间(创建了Session对象),同时生成一个Session id,并通过响应头的Set-Cookie:“JSESSIONID=XXXXXXX”命令,向客户端发送要求设置cookie的响应; 客户端收到响应后,在本机客户端设置了一个JSESSIONID=XXXXXXX的cookie信息,该cookie的过期时间为浏览器会话结束;
-
接下来客户端每次向同一个网站发送请求时,请求头都会带上该cookie信息(包含Session id); 然后,服务器通过读取请求头中的Cookie信息,获取名称为JSESSIONID的值,得到此次请求的Session id;
注意:服务器只会在客户端第一次请求响应的时候,在响应头上添加Set-Cookie:“JSESSIONID=XXXXXXX”信息,接下来在同一个会话的第二第三次响应头里,是不会添加Set- Cookie:“JSESSIONID=XXXXXXX”信息的; 而客户端是会在每次请求头的cookie中带上JSESSIONID信息;
-
10.HTTP状态码
HTTP状态码分类
HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:
HTTP状态码分类
分类—— 分类描述
1** —— 信息,服务器收到请求,需要请求者继续执行操作
2** —— 成功,操作被成功接收并处理
3**—— 重定向,需要进一步的操作以完成请求
4** ——客户端错误,请求包含语法错误或无法完成请求
5**—— 服务器错误,服务器在处理请求的过程中发生了错误