大家好,这次给大家带来了计算机网络六十二问,三万字,七十图详解,大概是全网最全的网络面试题。
建议大家收藏了慢慢看!
计算机网络体系结构,一般有三种:OSI 七层模型、TCP/IP 四层模型、五层结构。
三种网络体系结构
简单说,OSI是一个理论上的网络通信模型,TCP/IP是实际上的网络通信模型,五层结构就是为了介绍网络原理而折中的网络通信模型。
OSI 七层模型
OSI 七层模型是国际标准化组织(International Organization for Standardization)制定的一个用于计算机或通信系统间互联的标准体系。
TCP/IP 四层模型
五层体系结构
一张表格总结常见网络协议:
各层网络对应的网络协议
对于发送方而言,从上层到下层层层包装,对于接收方而言,从下层到上层,层层解开包装。
数据在各层之间的传输
这个过程类似写信,写一封信,每到一层,就加一个信封,写一些地址的信息。到了目的地之后,又一层层解封,传向下一个目的地。
这道题,大概的过程比较简单,但是有很多点可以细挖:DNS解析、TCP三次握手、HTTP报文格式、TCP四次挥手等等。
我们以输入www.baidu.com 为例:
www.baidu.comliu到显示主页
各个过程都使用了哪些协议?
www.baidu.comliu到显示主页过程使用的协议
DNS,英文全称是 domain name system,域名解析系统,它的作用也很明确,就是域名和 IP 相互映射。
DNS 的解析过程如下图:
DNS解析流程
假设你要查询 www.baidu.com 的 IP 地址:
域名服务器层级
com
的顶级域名服务器的IP地址的列表。com
的顶级域名服务器发送一个请求,返回负责baidu.com
的权限域名服务器的IP地址列表。具体来说,Socket 是一套标准,它完成了对 TCP/IP 的高度封装,屏蔽网络细节,以方便开发者更好地进行网络编程。
常见端口和服务
HTTP状态码首先应该知道个大概的分类:
几个常用的,面试之外,也应该记住:
常见HTTP状态码
之前写过一篇:程序员五一被拉去相亲,结果彻底搞懂了HTTP常用状态码,还比较有意思,可以看看。
说一下301和302的区别?
用一个比喻,301就是嫁人的新垣结衣,302就是有男朋友的长泽雅美。
HTTP请求方式1
其中,POST、DELETE、PUT、GET的含义分别对应我们最熟悉的增、删、改、查。
可以从以下几个方面来说明GET和POST的区别:
Get和Post区别
HTTP中的GET方法是通过URL传递数据的,但是URL本身其实并没有对数据的长度进行限制,真正限制GET长度的是浏览器。
例如IE浏览器对URL的最大限制是2000多个字符,大概2kb左右,像Chrome、Firefox等浏览器支持的URL字符数更多,其中FireFox中URL的最大长度限制是65536个字符,Chrome则是8182个字符。
这个长度限制也不是针对数据部分,而是针对整个URL。
HTTP协议定义了浏览器怎么向服务器请求文档,以及服务器怎么把文档传给浏览器。
HTTP请求的过程和原理
在浏览器和服务器之间的请求和响应的交互,必须按照规定的格式和遵循一定的规则,这些格式和规则就是超文本传输协议HTTP。
PS:这道题和上面浏览器输入网址发生了什么那道题大差不差。
HTTP报文有两种,HTTP请求报文和HTTP响应报文:
HTTP报文
HTTP请求报文
HTTP 请求报文的格式如下:
GET / HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*
HTTP 请求报文的第一行叫做请求行,后面的行叫做首部行,首部行后还可以跟一个实体主体。请求首部之后有一个空行,这个空行不能省略,它用来划分首部与实体。
请求行包含三个字段:
HTTP 响应报文
HTTP 响应报文的格式如下:
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84
<html>
<body>Hello World</body>
</html>
HTTP 响应报文的第一行叫做状态行,后面的行是首部行,最后是实体主体。
URI和URL
它们的主要区别在于,URL除了提供了资源的标识,还提供了资源访问的方式。这么比喻,URI 像是身份证,可以唯一标识一个人,而 URL 更像一个住址,可以通过 URL 找到这个人——人类住址协议://地球/中国/北京市/海淀区/xx职业技术学院/14号宿舍楼/525号寝/张三.男。
关键需要记住 HTTP/1.0 默认是短连接,可以强制开启,HTTP/1.1 默认长连接,HTTP/2.0 采用多路复用。
HTTP/1.0
Connection: keep-alive
这个字段,强制开启长连接。HTTP/1.1
HTTP/2.0
HTTP/3主要有两大变化,传输层基于UDP、使用QUIC保证UDP可靠性。
HTTP/2存在的一些问题,比如重传等等,都是由于TCP本身的特性导致的,所以HTTP/3在QUIC的基础上进行发展而来,QUIC(Quick UDP Connections)直译为快速UDP网络连接,底层使用UDP进行数据传输。
HTTP/3主要有这些特点:
我们拿一张图看一下HTTP协议的变迁:
HTTP协议变迁
什么是 HTTP 的长连接?
如何设置长连接?
通过在头部(请求和响应头)设置 Connection 字段指定为keep-alive
,HTTP/1.0 协议支持,但是是默认关闭的,从 HTTP/1.1 以后,连接默认都是长连接。
在什么时候会超时呢?
1. tcp_keepalive_intvl = 15
2. tcp_keepalive_probes = 5
3. tcp_keepalive_time = 1800
因为HTTP 是明⽂传输,存在安全上的风险:
窃听⻛险,⽐如通信链路上可以获取通信内容,用户账号被盗。
篡改⻛险,⽐如强制植⼊垃圾⼴告,视觉污染。
冒充⻛险,⽐如冒充淘宝⽹站,用户金钱损失。
HTTP和HTTPS
所以引入了HTTPS,HTTPS 在 HTTP 与 TCP 层之间加⼊了 SSL/TLS 协议,可以很好的解决了这些风险:
所以SSL/TLS 协议是能保证通信是安全的。
这道题有几个要点:公私钥、数字证书、加密、对称加密、非对称加密。
HTTPS 主要工作流程:
https主要流程
这里还画了一张更详尽的图:
https工作流程详图
首先,服务端的证书从哪来的呢?
为了让服务端的公钥被⼤家信任,服务端的证书都是由 CA (Certificate Authority,证书认证机构)签名的,CA就是⽹络世界⾥的公安局、公证中⼼,具有极⾼的可信度,所以由它来给各个公钥签名,信任的⼀⽅签发的证书,那必然证书也是被信任的。
证书签名和客户端校验-来源参考[2]
CA 签发证书的过程,如上图左边部分:
客户端校验服务端的数字证书的过程,如上图右边部分:
假如在HTTPS的通信过程中,中间人篡改了证书原文,由于他没有CA机构的私钥,所以CA公钥解密的内容就不一致。
这个无状态
的的状态
值的是什么?是客户端的状态,所以字面意思,就是HTTP协议中服务端不会保存客户端的任何信息。
比如当浏览器第一次发送请求给服务器时,服务器响应了;如果同个浏览器发起第二次请求给服务器时,它还是会响应,但是呢,服务器不知道你就是刚才的那个浏览器。
那有什么办法记录状态呢?
主要有两个办法,Session和Cookie。
先来看看什么是 Session 和 Cookie :
Cookie和Session
Session 和 Cookie 到底有什么不同呢?
Session 和 Cookie有什么关联呢?
可以使用Cookie记录Session的标识。
Session和Cookie的关联
分布式环境下Session怎么处理呢?
分布式环境下,客户端请求经过负载均衡,可能会分配到不同的服务器上,假如一个用户的请求两次没有落到同一台服务器上,那么在新的服务器上就没有记录用户状态的Session。
这时候怎么办呢?
可以使用Redis等分布式缓存来存储Session,在多台服务器之间共享。
Session共享
客户端无法使用Cookie怎么办?
有可能客户端无法使用Cookie,比如浏览器禁用Cookie,或者客户端是安卓、IOS等等。
这时候怎么办?SessionID怎么存?怎么传给服务端呢?
首先是SessionID的存储,可以使用客户端的本地存储,比如浏览器的sessionStorage。
接下来怎么传呢?
PS:TCP三次握手是最重要的知识点,一定要熟悉到问到即送分。
TCP提供面向连接的服务,在传送数据前必须建立连接,TCP连接是通过三次握手建立的。
TCP三次握手示意图
三次握手的过程:
最开始,客户端和服务端都处于CLOSE状态,服务端监听客户端的请求,进入LISTEN状态
客户端端发送连接请求,第一次握手 (SYN=1, seq=x),发送完毕后,客户端就进入 SYN_SENT 状态
服务端确认连接,第二次握手 (SYN=1, ACK=1, seq=y, ACKnum=x+1), 发送完毕后,服务器端就进入 SYN_RCV 状态。
客户端收到服务端的确认之后,再次向服务端确认,这就是**第三次握手 **(ACK=1,ACKnum=y+1),发送完毕后,客户端进入 ESTABLISHED 状态,当服务器端接收到这个包时,也进入 ESTABLISHED 状态。
TCP三次握手通俗比喻:
在二十年前的农村,电话没有普及,手机就更不用说了,所以,通信基本靠吼。
老张和老王是邻居,这天老张下地了,结果家里有事,热心的邻居老王赶紧跑到村口,开始叫唤老王。
老王:老张唉!我是老王,你能听到吗?
老张一听,是老王的声音:老王老王,我是老张,我能听到,你能听到吗?
老王一听,嗯,没错,是老张:老张,我听到了,我有事要跟你说。
"你老婆要生了,赶紧回家吧!"
老张风风火火地赶回家,老婆顺利地生了个带把的大胖小子。握手的故事充满了幸福和美满。
大白话三次握手
为什么不能是两次?
由于网络传输是有延时的(要通过网络光纤和各种中间代理服务器),在传输的过程中,比如客户端发起了 SYN=1 的第一次握手。
如果服务器端就直接创建了这个连接并返回包含 SYN、ACK 和 Seq 等内容的数据包给客户端,这个数据包因为网络传输的原因丢失了,丢失之后客户端就一直没有接收到服务器返回的数据包。
如果没有第三次握手告诉服务器端客户端收的到服务器端传输的数据的话,服务器端是不知道客户端有没有接收到服务器端返回的信息的。
服务端就认为这个连接是可用的,端口就一直开着,等到客户端因超时重新发出请求时,服务器就会重新开启一个端口连接。这样一来,就会有很多无效的连接端口白白地开着,导致资源的浪费。
无三次握手导致端口占
用还有一种情况是已经失效的客户端发出的请求信息,由于某种原因传输到了服务器端,服务器端以为是客户端发出的有效请求,接收后产生错误。
响应生效请求
所以我们需要“第三次握手”来确认这个过程:
通过第三次握手的数据告诉服务端,客户端有没有收到服务器“第二次握手”时传过去的数据,以及这个连接的序号是不是有效的。若发送的这个数据是“收到且没有问题
”的信息,接收后服务器就正常建立 TCP 连接,否则建立 TCP 连接失败,服务器关闭连接端口。由此减少服务器开销和接收到失效请求发生的错误。
为什么不是四次?
简单说,就是三次挥手已经足够创建可靠的连接,没有必要再多一次握手导致花费更多的时间建立连接。
第一次握手服务端未收到SYN报文
服务端不会进行任何的动作,而客户端由于一段时间内没有收到服务端发来的确认报文,等待一段时间后会重新发送SYN报文,如果仍然没有回应,会重复这个过程,直到发送次数超过最大重传次数限制,就会返回连接建立失败。
第二次握手客户端未收到服务端响应的ACK报文
客户端会继续重传,直到次数限制;而服务端此时会阻塞在accept()处,等待客户端发送ACK报文
第三次握手服务端为收到客户端发送过来的ACK报文
服务端同样会采用类似客户端的超时重传机制,如果重试次数超过限制,则accept()调用返回-1,服务端建立连接失败;而此时客户端认为自己已经建立连接成功,因此开始向服务端发送数据,但是服务端的accept()系统调用已经返回,此时不在监听状态,因此服务端接收到客户端发送来的数据时会发送RST报文给客户端,消除客户端单方面建立连接的状态。
ACK是为了告诉客户端传来的数据已经接收无误。
而传回SYN是为了告诉客户端,服务端响应的确实是客户端发送的报文。
第3次握手是可以携带数据的。
此时客户端已经处于ESTABLISHED状态。对于客户端来说,它已经建立连接成功,并且确认服务端的接收和发送能力是正常的。
第一次握手不能携带数据是出于安全的考虑,因为如果允许携带数据,攻击者每次在SYN报文中携带大量数据,就会导致服务端消耗更多的时间和空间去处理这些报文,会造成CPU和内存的消耗。
什么是半连接队列?
TCP 进入三次握手前,服务端会从 CLOSED 状态变为 LISTEN 状态, 同时在内部创建了两个队列:半连接队列(SYN 队列)和全连接队列(ACCEPT 队列)。
三次握手中创建的队列
顾名思义,半连接队列存放的是三次握手未完成的连接,全连接队列存放的是完成三次握手的连接。
什么是SYN Flood ?
SYN Flood 是一种典型的 DDos 攻击,它在短时间内,伪造不存在的 IP 地址, 向服务器发送大量SYN 报文。当服务器回复 SYN+ACK 报文后,不会收到 ACK 回应报文,那么SYN队列里的连接旧不会出对队,久⽽久之就会占满服务端的 SYN 接收队列(半连接队列),使得服务器不能为正常⽤户服务。
SYN攻击
那有什么应对方案呢?
主要有 syn cookie 和 SYN Proxy 防火墙等。
PS:问完三次握手,常常也会顺道问问四次挥手,所以也是必须掌握知识点。
TCP四次挥手
TCP 四次挥手过程:
大白话说四次挥手:
假如单身狗博主有一个女朋友—由于博主上班九九六,下班肝博客,导致没有时间陪女朋友,女朋友忍无可忍。
沙雕博主小心翼翼地装起了自己的青轴机械键盘。
挥手的故事总充满了悲伤和遗憾!
大白话四次挥手
再来回顾下四次挥手双方发 FIN
包的过程,就能理解为什么需要四次了。
FIN
时,仅仅表示客户端不再发送数据了但是还能接收数据。FIN
报文时,先回一个 ACK
应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN
报文给客户端来表示同意现在关闭连接。从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK
和 FIN
一般都会分开发送,从而比三次握手导致多了一次。
为什么需要等待?
1. 为了保证客户端发送的最后一个 ACK 报文段能够到达服务端。 这个 ACK 报文段有可能丢失,因而使处在 LAST-ACK 状态的服务端就收不到对已发送的 FIN + ACK 报文段的确认。服务端会超时重传这个 FIN+ACK 报文段,而客户端就能在 2MSL 时间内(超时 + 1MSL 传输)收到这个重传的 FIN+ACK 报文段。接着客户端重传一次确认,重新启动 2MSL 计时器。最后,客户端和服务器都正常进入到 CLOSED 状态。
2. 防止已失效的连接请求报文段出现在本连接中。客户端在发送完最后一个 ACK 报文段后,再经过时间 2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个连接中不会出现这种旧的连接请求报文段。
为什么等待的时间是2MSL?
MSL 是 Maximum Segment Lifetime,报⽂最⼤⽣存时间,它是任何报⽂在⽹络上存在的最⻓时间,超过这个时间报⽂将被丢弃。
TIME_WAIT 等待 2 倍的 MSL,⽐较合理的解释是:⽹络中可能存在来⾃发送⽅的数据包,当这些发送⽅的数据包被接收⽅处理后⼜会向对⽅发送响应,所以⼀来⼀回需要等待 2 倍的时间。
2MSL恰好一个来回
⽐如如果被动关闭⽅没有收到断开连接的最后的 ACK 报⽂,就会触发超时重发 Fin 报⽂,另⼀⽅接收到 FIN 后,会重发 ACK 给被动关闭⽅, ⼀来⼀去正好 2 个 MSL。
除时间等待计时器外,TCP 还有一个保活计时器(keepalive timer)。
设想这样的场景:客户已主动与服务器建立了 TCP 连接。但后来客户端的主机突然发生故障。显然,服务器以后就不能再收到客户端发来的数据。因此,应当有措施使服务器不要再白白等待下去。这就需要使用保活计时器了。
服务器每收到一次客户端的数据,就重新设置保活计时器,时间的设置通常是两个小时。若两个小时都没有收到客户端的数据,服务端就发送一个探测报文段,以后则每隔 75 秒钟发送一次。若连续发送 10 个探测报文段后仍然无客户端的响应,服务端就认为客户端出了故障,接着就关闭这个连接。
CLOSE-WAIT状态有什么意义?
服务端收到客户端关闭连接的请求并确认之后,就会进入CLOSE-WAIT状态。此时服务端可能还有一些数据没有传输完成,因此不能立即关闭连接,而CLOSE-WAIT状态就是为了保证服务端在关闭连接之前将待发送的数据处理完。
TIME-WAIT有什么意义?
TIME-WAIT状态发生在第四次挥手,当客户端向服务端发送ACK确认报文后进入TIME-WAIT状态。
它存在的意义主要是两个:
TIME_WAIT状态的作用
防⽌旧连接的数据包
如果客户端收到服务端的FIN报文之后立即关闭连接,但是此时服务端对应的端口并没有关闭,如果客户端在相同端口建立新的连接,可能会导致新连接收到旧连接残留的数据包,导致不可预料的异常发生。
保证连接正确关闭
假设客户端最后一次发送的ACK包在传输的时候丢失了,由于TCP协议的超时重传机制,服务端将重发FIN报文,如果客户端没有维持TIME-WAIT状态而直接关闭的话,当收到服务端重新发送的FIN包时,客户端就会使用RST包来响应服务端,导致服务端以为有错误发生,然而实际关闭连接过程是正常的。
TIME_WAIT 状态过多会导致什么问题?
如果服务器有处于 TIME-WAIT 状态的 TCP,则说明是由服务器⽅主动发起的断开请求。
过多的 TIME-WAIT 状态主要的危害有两种:
第⼀是内存资源占⽤;
第⼆是对端⼝资源的占⽤,⼀个 TCP 连接⾄少消耗⼀个本地端⼝;
怎么解决TIME_WAIT 状态过多?
看一下TCP报文首部的格式:
TCP报文首部的格式
TCP主要提供了检验和、序列号/确认应答、超时重传、最大消息长度、滑动窗口控制等方法实现了可靠性传输。
TCP保证可靠性的方法
TCP校验和
3 . 序列号/确认应答:TCP 给发送的每一个包进行编号,接收方会对收到的包进行应答,发送方就会知道接收方是否收到对应的包,如果发现没有收到,就会重发,这样就能保证数据的完整性。就像老师上课,会问一句,这一章听懂了吗?没听懂再讲一遍。
序列号/确认应答
4 . **流量控制:**TCP 连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议。(TCP 利用滑动窗口实现流量控制)
滑动窗口简图
5 . 最大消息长度:在建立TCP连接的时候,双方约定一个最大的长度(MSS)作为发送的单位,重传的时候也是以这个单位来进行重传。理想的情况下是该长度的数据刚好不被网络层分块。
最大消息长度
6 . **超时重传:**超时重传是指发送出去的数据包到接收到确认包之间的时间,如果超过了这个时间会被认为是丢包了,需要重传。
超时重传
7 . **拥塞控制:**如果网络非常拥堵,此时再发送数据就会加重网络负担,那么发送的数据段很可能超过了最大生存时间也没有到达接收方,就会产生丢包问题。为此TCP引入慢启动机制,先发出少量数据,就像探路一样,先摸清当前的网络拥堵状态后,再决定按照多大的速度传送数据。
拥塞控制简略示意图
TCP 提供了一种机制,可以让发送端根据接收端的实际接收能力控制发送的数据量,这就是流量控制。
TCP 通过滑动窗口来控制流量,我们看下简要流程:
TCP流量控制
SND.NXT
会右移 200 个字节,也就是说当前的可用窗口减少了 200 个字节。TCP 发送一个数据,如果需要收到确认应答,才会发送下一个数据。这样的话就会有个缺点:效率会比较低。
“用一个比喻,我们在微信上聊天,你打完一句话,我回复一句之后,你才能打下一句。假如我没有及时回复呢?你是把话憋着不说吗?然后傻傻等到我回复之后再接着发下一句?”
为了解决这个问题,TCP 引入了窗口,它是操作系统开辟的一个缓存空间。窗口大小值表示无需等待确认应答,而可以继续发送数据的最大值。
TCP 头部有个字段叫 win,也即那个 16 位的窗口大小,它告诉对方本端的 TCP 接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度,从而达到流量控制的目的。
“通俗点讲,就是接受方每次收到数据包,在发送确认报文的时候,同时告诉发送方,自己的缓存区还有多少空余空间,缓冲区的空余空间,我们就称之为接受窗口大小。这就是 win。”
TCP 滑动窗口分为两种: 发送窗口和接收窗口。发送端的滑动窗口包含四大部分,如下:
发送端滑动窗口
接收方的滑动窗口包含三大部分,如下:
接收方滑动窗口
Nagle 算法和延迟确认是干什么的?
当我们 TCP 报⽂的承载的数据⾮常⼩的时候,例如⼏个字节,那么整个⽹络的效率是很低的,因为每个 TCP 报⽂中都会有 20 个字节的 TCP 头部,也会有 20 个字节的 IP 头部,⽽数据只有⼏个字节,所以在整个报⽂中有效数据占有的比例就会⾮常低。
小数据情况
这就好像快递员开着⼤货⻋送⼀个⼩包裹⼀样浪费。
那么就出现了常⻅的两种策略,来减少⼩报⽂的传输,分别是:
Nagle 算法
Nagle 算法:任意时刻,最多只能有一个未被确认的小段。所谓 “小段”,指的是小于 MSS 尺寸的数据块,所谓 “未被确认”,是指一个数据块发送出去后,没有收到对方发送的 ACK 确认该数据已收到。
Nagle 算法的策略:
只要没满⾜上⾯条件中的⼀条,发送⽅⼀直在囤积数据,直到满⾜上⾯的发送条件。
延迟确认
事实上当没有携带数据的 ACK,它的⽹络效率也是很低的,因为它也有 40 个字节的 IP 头 和 TCP 头,但却没有携带数据报⽂。
为了解决 ACK 传输效率低问题,所以就衍⽣出了 TCP 延迟确认。
TCP 延迟确认的策略:
一般情况下,Nagle 算法和延迟确认不能一起使用,Nagle 算法意味着延迟发,延迟确认意味着延迟接收,两个凑在一起就会造成更大的延迟,会产生性能问题。
什么是拥塞控制?不是有了流量控制吗?
前⾯的流量控制是避免发送⽅的数据填满接收⽅的缓存,但是并不知道整个⽹络之中发⽣了什么。
⼀般来说,计算机⽹络都处在⼀个共享的环境。因此也有可能会因为其他主机之间的通信使得⽹络拥堵。
在⽹络出现拥堵时,如果继续发送⼤量数据包,可能会导致数据包时延、丢失等,这时 TCP 就会重传数据,但是⼀重传就会导致⽹络的负担更重,于是会导致更⼤的延迟以及更多的丢包,这个情况就会进⼊恶性循环被不断地放⼤....
所以,TCP 不能忽略整个网络中发⽣的事,它被设计成⼀个⽆私的协议,当⽹络发送拥塞时,TCP 会⾃我牺牲,降低发送的数据流。
于是,就有了拥塞控制,控制的⽬的就是避免发送⽅的数据填满整个⽹络。
就像是一个水管,不能让太多的水(数据流)流入水管,如果超过水管的承受能力,水管会被撑爆(丢包)。
破解的水管-图片来源网络
发送方维护一个拥塞窗口 cwnd(congestion window) 的变量,调节所要发送数据的量。
什么是拥塞窗⼝?和发送窗⼝有什么关系呢?
拥塞窗⼝ cwnd是发送⽅维护的⼀个的状态变量,它会根据⽹络的拥塞程度动态变化的。
发送窗⼝ swnd 和接收窗⼝ rwnd 是约等于的关系,那么由于加⼊了拥塞窗⼝的概念后,此时发送窗⼝的值是swnd = min(cwnd, rwnd),也就是拥塞窗⼝和接收窗⼝中的最⼩值。
拥塞窗⼝ cwnd 变化的规则:
拥塞控制有哪些常用算法?
拥塞控制主要有这几种常用算法:
拥塞控制常用算法
慢启动算法,慢慢启动。
它表示 TCP 建立连接完成后,一开始不要发送大量的数据,而是先探测一下网络的拥塞程度。由小到大逐渐增加拥塞窗口的大小,如果没有出现丢包,每收到一个 ACK,就将拥塞窗口 cwnd 大小就加 1(单位是 MSS)。每轮次发送窗口增加一倍,呈指数增长,如果出现丢包,拥塞窗口就减半,进入拥塞避免阶段。
举个例子:
慢启动算法
发包的个数是指数性的增⻓。
慢启动呈指数型增长
为了防止 cwnd 增长过大引起网络拥塞,还需设置一个慢启动阀值 ssthresh(slow start threshold)状态变量。当cwnd
到达该阀值后,就好像水管被关小了水龙头一样,减少拥塞状态。即当 cwnd >ssthresh 时,进入了拥塞避免算法。
一般来说,慢启动阀值 ssthresh 是 65535 字节,cwnd
到达慢启动阀值后
显然这是一个线性上升的算法,避免过快导致网络拥塞问题。
接着上面慢启动的例子,假定 ssthresh 为 8 ::
拥塞避免算法
当网络拥塞发生丢包时,会有两种情况:
如果是发生了 RTO 超时重传,就会使用拥塞发生算法
拥塞发生算法这种方式就像是飙车的时候急刹车,还飞速倒车,这。。。
其实还有更好的处理方式,就是快速重传。发送方收到 3 个连续重复的 ACK 时,就会快速地重传,不必等待 RTO 超时再重传。
发⽣快速重传的拥塞发⽣算法:
快速重传和快速恢复算法一般同时使用。快速恢复算法认为,还有 3 个重复 ACK 收到,说明网络也没那么糟糕,所以没有必要像 RTO 超时那么强烈。
正如前面所说,进入快速恢复之前,cwnd 和 sshthresh 已被更新:
- sshthresh = cwnd
然后,进⼊快速恢复算法如下:
快速恢复算法
重传包括超时重传、快速重传、带选择确认的重传(SACK)、重复 SACK 四种。
TCP重传分类
超时重传,是 TCP 协议保证数据可靠性的另一个重要机制,其原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果没有得到发送的数据报的 ACK 报文,那么就重新发送数据,直到发送成功为止。
超时时间应该设置为多少呢?
先来看下什么叫 RTT(Round-Trip Time,往返时间)。
RTT
RTT 就是数据完全发送完,到收到确认信号的时间,即数据包的一次往返时间。
超时重传时间,就是 RTO(Retransmission Timeout)。那么,RTO 到底设置多大呢?
一般来说,RTO 略微大于 RTT,效果是最佳的。
其实,RTO 有个标准方法的计算公式,也叫 Jacobson / Karels 算法。
SRTT = (1 - α) * SRTT + α * RTT //求 SRTT 的加权平均
2 . 其次,计算 RTTVAR (round-trip time variation)
RTTVAR = (1 - β) * RTTVAR + β * (|RTT - SRTT|) //计算 SRTT 与真实值的差距
3 . 最后,得出最终的 RTO
RTO = µ * SRTT + ∂ * RTTVAR = SRTT + 4·RTTVAR
在 Linux 下,α = 0.125,β = 0.25, μ = 1,∂ = 4。别问这些参数是怎么来的,它们是大量实践,调出的最优参数。
超时重传不是十分完美的重传方案,它有这些缺点:
并且,对于 TCP,如果发生一次超时重传,时间间隔下次就会加倍。
TCP 还有另外⼀种快速重传(Fast Retransmit)机制,它不以时间为驱动,⽽是以数据驱动重传。
它不以时间驱动,而是以数据驱动。它是基于接收端的反馈信息来引发重传的。
可以用它来解决超时重发的时间等待问题,快速重传流程如下:
快速重传流程
在上图,发送⽅发出了 1,2,3,4,5 份数据:
快速重传机制只解决了⼀个问题,就是超时时间的问题,但是它依然⾯临着另外⼀个问题。就是重传的时候,是重传之前的⼀个,还是重传所有的问题。
⽐如对于上⾯的例⼦,是重传 Seq2 呢?还是重传 Seq2、Seq3、Seq4、Seq5 呢?因为发送端并不清楚这连续的三个 Ack 2 是谁传回来的。
根据 TCP 不同的实现,以上两种情况都是有可能的。可⻅,这是⼀把双刃剑。
为了解决不知道该重传哪些 TCP 报⽂,于是就有 SACK ⽅法。
为了解决应该重传多少个包的问题? TCP 提供了带选择确认的重传(即 SACK,Selective Acknowledgment)。
SACK 机制就是,在快速重传的基础上,接收方返回最近收到报文段的序列号范围,这样发送方就知道接收方哪些数据包是没收到的。这样就很清楚应该重传哪些数据包。
SACK机制-来源参考[3]
如上图中,发送⽅收到了三次同样的 ACK 确认报⽂,于是就会触发快速重发机制,通过 SACK 信息发现只有200~299 这段数据丢失,则重发时,就只选择了这个 TCP 段进⾏重发。
D-SACK,英文是 Duplicate SACK,是在 SACK 的基础上做了一些扩展,主要用来告诉发送方,有哪些数据包,自己重复接受了。
DSACK 的目的是帮助发送方判断,是否发生了包失序、ACK 丢失、包重复或伪重传。让 TCP 可以更好的做网络流控。
例如ACK丢包导致的数据包重复:
ACK丢包-来源参考[3]
3499)
TCP 的粘包和拆包更多的是业务上的概念!
什么是TCP粘包和拆包?
TCP 是面向流,没有界限的一串数据。TCP 底层并不了解上层业务数据的具体含义,它会根据 TCP 缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被 TCP 拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的 TCP 粘包和拆包问题。
TCP 的粘包和拆包
为什么会产生粘包和拆包呢?
那怎么解决呢?
UDP问的不多,基本上是被拿来和TCP比较。
最根本区别:TCP 是面向连接,而 UDP 是无连接。
TCP和UDP区别
可以这么形容:TCP是打电话,UDP是大喇叭。
TCP和UDP比喻
说说TCP和UDP的应用场景?
PS:这是多年前的老题了,拉出来怀怀旧。
QQ使用UDP
简单总结一下:UDP协议是无连接方式的协议,它的效率高,速度快,占资源少,对服务器的压力比较小。但是其传输机制为不可靠传送,必须依靠辅助的算法来完成传输控制。QQ采用的通信协议以UDP为主,辅以TCP协议。
UDP在传输数据之前不需要先建立连接,远地主机的运输层在接收到UDP报文后,不需要确认,提供不可靠交付。总结就以下四点:
更准确地说,DNS既使用TCP又使用UDP。
当进行区域传送(主域名服务器向辅助域名服务器传送变化的那部分数据)时会使用TCP,因为数据同步传送的数据量比一个请求和应答的数据量要多,而TCP允许的报文长度更长,因此为了保证数据的正确性,会使用基于可靠连接的TCP。
当客户端想DNS服务器查询域名(域名解析)的时候,一般返回的内容不会超过UDP报文的最大长度,即512字节,用UDP传输时,不需要创建连接,从而大大提高了响应速度,但这要求域名解析服务器和域名服务器都必须自己处理超时和重传从而保证可靠性。
IP协议是什么?
IP协议(Internet Protocol)又被称为互联网协议,是支持网间互联的数据包协议,工作在网际层,主要目的就是为了提高网络的可扩展性。
通过网际协议IP,可以把参与互联的,性能各异的网络看作一个统一的网络。
虚拟IP网
和传输层TCP相比,IP协议是一种无连接/不可靠、尽力而为的数据包传输服务,和TCP协议一起构成了TCP/IP协议的核心。
IP协议有哪些作用?
IP协议主要有以下几个作用:
传输层协议和网络层协议有什么区别?
网络层协议负责提供主机间的逻辑通信;传输层协议负责提供进程间的逻辑通信。
一个IP地址在这鞥个互联网范围内是惟一的,一般可以这么认为,IP 地址 = {<网络号>,<主机号>}。
IP 地址分为 A,B,C,D,E 五大类:
IP地址分类
假如你有多个不用的绰号,你的朋友可以用其中任何一个绰号叫你,但你的身份证号码却是惟一的。但同时你的绰号也可能和别人重复,假如你不在,有人叫你的绰号,其它人可能就答应了。
一个域名可以对应多个IP,但这种情况DNS做负载均衡的,在用户访问过程中,一个域名只能对应一个IP。
而一个IP却可以对应多个域名,是一对多的关系。
我们知道,IP地址有32位,可以标记2的32次方个地址,听起来很多,但是全球的网络设备数量已经远远超过这个数字,所以IPV4地址已经不够用了,那怎么解决呢?
IPV4不够解决办法
ARP 协议,Address Resolution Protocol,地址解析协议,它是用于实现 IP 地址到 MAC 地址的映射。
ARP 协议作用
MAC地址和IP地址都有什么作用?
为什么有了MAC地址还需要IP地址?
如果我们只使用MAC地址进行寻址的话,我们需要路由器记住每个MAC地址属于哪个子网,不然一次路由器收到数据包都要满世界寻找目的MAC地址。而我们知道MAC地址的长度为48位,也就是最多共有2的48次方个MAC地址,这就意味着每个路由器需要256T的内存,显然是不现实的。
和MAC地址不同,IP地址是和地域相关的,在一个子网中的设备,我们给其分配的IP地址前缀都是一样的,这样路由器就能根据IP地址的前缀知道这个设备属于哪个子网,剩下的寻址就交给子网内部实现,从而大大减少了路由器所需要的内存。
为什么有了IP地址还需要MAC地址?
IP地址和MAC地址
ICMP(Internet Control Message Protocol) ,网际控制报文协议。
比如我们日常使用得比较多的 ping,就是基于 ICMP 的。
ping,Packet Internet Groper,是一种因特网包探索器,用于测试网络连接量的程序。Ping 是工作在 TCP/IP 网络体系结构中应用层的一个服务命令, 主要是向特定的目的主机发送 ICMP(Internet Control Message Protocol 因特网报文控制协议) 请求报文,测试目的站是否可达及了解其有关状态。
ping百度
一般来说,ping 可以用来检测网络通不通。它是基于ICMP
协议工作的。假设机器 A ping 机器 B,工作过程如下:
网络安全攻击主要分为两种类型,被动攻击和主动攻击:
主动攻击和被动攻击
DNS劫持即域名劫持,是通过将原域名对应的IP地址进行替换,从而使用户访问到错误的网站,或者使用户无法正常访问网站的一种攻击方式。
DNS劫持示意图
域名劫持往往只能在特定的网络范围内进行,范围外的DNS服务器能够返回正常的IP地址。攻击者可以冒充原域名所属机构,通过电子邮件的方式修改组织机构的域名注册信息,或者将域名转让给其它主持,并将新的域名信息保存在所指定的DNS服务器中,从而使用户无法对原域名来进行解析以访问目标地址。
DNS劫持的步骤是什么样的?
怎么应对DNS劫持?
什么是 CSRF 攻击?
CSRF,跨站请求伪造(英文全称是 Cross-site request forgery),是一种挟持用户在当前已登录的 Web 应用程序上执行非本意的操作的攻击方法。
CSRF 是如何攻击的呢?
来看一个例子:
CSRF典型例子
怎么应对 CSRF 攻击呢?
检查 Referer 字段
HTTP头中的Referer字段记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,而如果黑客要对其实施 CSRF攻击,他一般只能在他自己的网站构造请求。因此,可以通过验证Referer值来防御CSRF 攻击。
添加校验 token
以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有token或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
敏感操作多重校验
对一些敏感的操作,除了需要校验用户的认证信息,还可以通过邮箱确认、验证码确认这样的方式多重校验。
请求太多服务器着不住
DOS: (Denial of Service), 翻译过来就是拒绝服务, 一切能引起拒绝 行为的攻击都被称为 DOS 攻击。最常见的 DoS 攻击就有计算机网络宽带攻击、连通性攻击。
DDoS: (Distributed Denial of Service),翻译过来是分布式拒绝服务。是指处于不同位置的多个攻击者同时向一个或几个目标发动攻击,或者一个攻击者控制了位于不同位置的多台机器,并利用这些机器对受害者同时实施攻击。
主要形式有流量攻击和资源耗尽攻击,常见的 DDoS攻击有:SYN Flood、Ping of Death、ACK Flood、UDP Flood 等。
DRDoS: (Distributed Reflection Denial of Service),中文是分布式反射拒绝服务,该方式靠的是发送大量带有被害者 IP 地址的数据包给攻击主机,然后攻击主机对 IP 地址源做出大量回应,从而形成拒绝服务攻击。
如何防范DDoS?
针对DDoS中的流量攻击,最直接的方法是增加带宽,理论上只要带宽大于攻击流量就可以了,但是这种方法成本非常高。在有充足带宽的前提下,我们应该尽量提升路由器、网卡、交换机等硬件设施的配置。
针对资源耗尽攻击,我们可以升级主机服务器硬件,在网络带宽得到保证的前提下,使得服务器能够有效对抗海量的SYN攻击包。我们也可以安装专业的抗DDoS防火墙,从而对抗SYN Flood等流量型攻击。瓷碗,负载均衡,CDN等技术都能有效对抗DDos攻击。
XSS 攻击也是比较常见,XSS,叫跨站脚本攻击(Cross-Site Scripting),因为会与层叠样式表 (Cascading Style Sheets, CSS) 的缩写混淆,因此有人将跨站脚本攻击缩写为 XSS。它指的是恶意攻击者往 Web 页面里插入恶意 html 代码,当用户浏览网页的时候,嵌入其中 Web 里面的 html 代码会被执行,从而达到恶意攻击用户的特殊目的。
XSS 攻击一般分三种类型:存储型 、反射型 、DOM 型 XSS
XSS 是如何攻击的呢?
简单说,XSS的攻击方式就是想办法“教唆”用户的浏览器去执行一些这个网页中原本不存在的前端代码。
拿反射型举个例子吧,流程图如下:
一个典型的XSS
如何应对 XSS 攻击?
<a href="xxx"
等,要校验内容,禁止以 script 开头的非法链接。对称加密:指加密和解密使用同一密钥,优点是运算速度较快,缺点是如何安全将密钥传输给另一方。常见的对称加密算法有:DES、AES 等。
对称加密
非对称加密:指的是加密和解密使用不同的密钥(即公钥和私钥)。公钥与私钥是成对存在的,如果用公钥对数据进行加密,只有对应的私钥才能解密。常见的非对称加密算法有 RSA。
非对称加密
RSA
采用非对称加密的方式,采用公钥进行加密,私钥解密的形式。其私钥长度一般较长,由于需要大数的乘幂求模等运算,其运算速度较慢,不合适大量数据文件加密。
AES
采用对称加密的方式,其秘钥长度最长只有256个比特,加密和解密速度较快,易于硬件实现。由于是对称加密,通信双方在进行数据传输前需要获知加密密钥。
参考:
[1]. [2W字!梳理50道经典计算机网络面试题(收藏版)]
[2]. 小林coding 《图解网络》
[3].“三次握手,四次挥手”这么讲,保证你忘不了:https://juejin.cn/post/6965544021833809928
[4]. 艾小仙 《我要进大厂》
[5]. 《图解HTTP》
[6]. 浅析DNS域名解析过程:https://cloud.tencent.com/developer/news/324975
[7]. 「2021」高频前端面试题汇总之计算机网络篇:https://juejin.cn/post/6908327746473033741
[8].计算机网络:https://juejin.cn/post/6943748667333427207
[9]. 谢希仁编著《计算机网络》
[10].《图解TCP/IP》
[11].TCP的可靠性传输是如何保证的:https://zhuanlan.zhihu.com/p/112317245
[12].前端安全系列(一):如何防止XSS攻击?:https://tech.meituan.com/2018/09/27/fe-security.html
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8