计算机网络知识复习

HTTP 1.0 和 2.0 有什么区别?

HTTP/1.0 版本主要增加以下几点:
1.增加了 HEAD、POST 等新方法。
2.增加了响应状态码。
3.引入了头部,即请求头和响应头。
4.在请求中加入了 HTTP 版本号。
5.引入了 Content-Type ,使得传输的数据不再限于文本。

HTTP/1.1 版本主要增加以下几点:
1.新增了连接管理即 keepalive ,允许持久连接。
2.支持 pipeline,无需等待前面的请求响应,即可发送第二次请求。
3.允许响应数据分块(chunked),即响应的时候不标明Content-Length,客户端就无法断开连接,直到收到服务端的 EOF,利于传输大文件。
4.新增缓存的控制和管理。
5.加入了 Host 头,用在你一台机子部署了多个主机,然后多个域名解析又是同一个IP,此时加入了 Host 头就可以判断你到底是要访问哪个主机。

HTTP/2 版本主要增加以下几点:
1.是二进制协议,不再是纯文本上
2.支持一个TCP 连接发起多请求,移除了pipeline。
3.利用 HPACK 压缩头部,减少数据传输量。
4.允许服务端主动推送数据。

HTTP 2.0 和 3.0 有什么区别?

痛点来自于 HTTP 依赖的 TCP。TCP 是面向可靠的、有序的传输协议,因此会有失败重传和按序机制,而 HTTP/2 是所有流共享一个 TCP 连接所以会有 TCP 层面的队头阻塞,当发生重传时会影响多个请求响应。
并且 TCP 是基于四元组(源IP,源端口,目标IP,目标端口)来确定连接的,而在移动网络的情况下IP 地址会频繁的换,这会导致反复的建连。
还有 TCP 与 TLS 的叠加握手,增加了延时。
问题就出在 TCP 身上,所以 Google 就把目光瞄向了 UDP。
QUIC 引入了个叫 Connection ID 来标识一个链接,所以切换网络之后可以复用这个连接,达到0RTT 就能开始传输。

HTTP/2 提到的 HPACK,这个是依赖 TCP 的可靠、有序传输的,于是 QUC 得搞了个 QPACK,也采用了静态表、动态表和哈夫曼编码。
它丰富了 HTTP/2 的静态表,从 61 项加到了 98 项。
上面提到的动态表,是用来存储末包含在静态表中的头部项,假设动态表还未收到,后面来解头部的时候肯定要被阻塞的。所以 QPACK 就另开一条路,在单向的 Stream 里传输动态表的编解码,单向传输好了,接受端到才能开始解码也就是说还没好你就先别管,防止做一半卡住了。
**那还有前面提到的 TCP 队头阻塞, QUIC 是怎么解决的呢?**毕竟它也要保证有序和可靠啊。
因为 TCP 不认识每个流分别是哪个请求的,所以它只能全部阻塞住,而 QUIC 知道,因此比如请求 A 丢包了我就把 A卡住了就行,请求 B完全可以全部放行,丝毫不受影响。
可以看到基于 UDP 的 QUIC 还是很强大的,而且人家用户多,在 2018 年,互联网标准化组织IETF 提议将 HTTPover QUIc 更名为 HTTP/3 并获得批准。

HTTP 和 HTTPS 有什么区别?

http 是明文传输,而 https 是加密传输,所以基本上市面上的网站用的都是 htps 协议,因为明文传输很容易被中间人抓包然后获取一些敏感信息。
而加密传输中间人只能获取加密的数据
https 是基于http上又加了SSL(Secure Sockets Layer)或TLS(Transport Layer Security)协议来实现的加密传输。
https 传输的过程使用对称加密,这比非对称加密更加高效。

端口不一样,http是80,https是443。 https相较于http在三次握手之后还需要进行SSL/TLS 的握手过程,才可进入加密报文传输。

TCP 是用来解决什么问题?

TCP 即 Transmission Control Protocol,可以看到是一个传输控制协议,
控制可靠、按序地传输以及端与端之间的流量控制。拥塞控制,需要为整体网络的情况考虑。

TCP 和 UDP 有什么区别?

tcp 是面向连接的协议,它提供有序、可靠的数据传输,有确认应答、超时重传、流是控制和拥塞控制等机制。
udp 是无连接协议,它不保证数据的可靠性,仅传输数据,也不会等待对方的响应,没有顺序、流量和拥塞控制,也因此它的传输速度更快。
tcp主要用于可靠传输场景、例如文件传输、电商网站等。
udp主要用于游戏、直播等对数据可靠性要求不高的场景。

为什么要 TCP,IP 层实现控制不行么?

我们知道网络是分层实现的,网络协议的设计就是为了通信,从链路层到IP 层其实就已经可以完成通信了。
你看链路层不可或缺毕竟咱们电脑都是通过链路相互连接的,然后IP充当了地址的功能,所以通过IP 咱们找到了对方就可以进行通信了。
那加个 TCP 层干啥?IP 层实现控制不就完事了嘛?
之所以要提取出一个 TCP 层来实现控制是因为IP 层涉及到的设备更多一条数据在网络上传输需要经过很多设备,而设备之间需要靠 IP 来寻址。
假设IP 层实现了控制,那是不是涉及到的设备都需要关心很多事情?整体传输的效率是不是大打折扣了?

举个例子,假如 A要传输给F一个积木,但是无法直接传输到,需要经过 B、C、D、E这几个中转站之手。这里有两种情况:
假设 BCDE 都需要关心这个积木搭错了没,都拆开包裹仔细的看看,没问题了再装回去,最终到了F的手中。
假设 BCDE 都不关心积木的情况,来啥包裹只管转发就完事了,由最终的F自己来检查这个积木答错了没。
你觉得哪种效率高?明显是第二种,转发的设备不需要关心这些事,只管转发就完事!
所以把控制的逻辑独立出来成 TCP 层,让真正的接收端来处理,这样网络整体的传输效率就高了。

TCP 的粘包和拆包能说说吗?

粘包与半包只有在 TCP 传输的时候才会有,像 UDP 是不会有这种情况的,原因是因为 TCP 是面向流的,数据之间没有界限的,而 UDP 是有的界限的。
如果熟悉 TCP 和 UDP 报文格式的同学肯定知道,TCP 的包没有报文长度,而 UDP 的包有报文长度,这也说明了TCP 为什么是流式。
所以我为什么说上面的例子不太恰当,因为现实生活中快递的包裹之间其实是有界限的,TCP 则像流水,没有明确的界限。
然后 TCP 有发送缓冲区的概念,UDP 实际上是没这个概念。
假设 TCP 一次传输的数据大小超过发送缓冲区大小,那么一个完整的报文就需要被拆分成两个或更多的小报文这可能会产生半包的情况,当接收端收到不完整的数据,是无法解析成功的。
如果 TCP 一次传输的数据大小小于发送缓冲区,那么可能会跟别的报文合并起来一块发送,这就是粘包。

说说 TCP 的三次握手?

image-20240807105337296

客户端首先发送一个SYN(同步序列编号)消息给服务器,服务器收到后回复一个SYN-ACK(同步序列编号-确认)消息,最后客户端再发送一个ACK(确认)消息确认服务器已经收到SYN-ACK消息,从而完成三次握手,建立起-个可靠的TCP连接。

初始序列号 ISN 怎么取值的?

ISN:初始化序列号(initial sequence number),是在建立tcp三次握手的时候,存储在TCP头部的序列号位置中的数字的代称。也就是说,告诉对方我将要开始发送的初始化序列号是多少,两边都要发这个ISN,即tcp三次握手中第一次握手的SYN包和第二次握手的SYN+ACK包中都有这个数值。这个ISN的具体数值是不固定的。

如果写死一个值,比如0,那么假设已经建立好连接了,client 也发了很多包比如已经第 20 个包了然后网络断了之后 client 重新,端口号还是之前那个,然后序列号又从0开始,此时服务端返回第 20 个包的ack,客户端是不是傻了?
所以 RFC793 中认为 ISN 要和一个假的时钟绑定在一起
ISN 每四微秒加一,当超过 2的 32 次方之后又从0开始,要四个半小时左右发生ISN 回绕。
所以 ISN 变成一个递增值,真实的实现还需要加一些随机值在里面,防止被不法份子猜到 ISN。

初始序列号(ISN)的选取涉及多个考虑因素,包括连接唯一性、防止旧数据包干扰和增强安全性。现代系统通常采用时间戳法、随机化算法或两者结合的方法来生成ISN,以确保连接的可靠性和安全性。通过这些方法,ISN在保证唯一性和不可预测性方面发挥了重要作用,从而有效防止了TCP序列号预测攻击。

SYN 超时了怎么处理?

cient 发送 SYN 至 server 然后就挂了,此时 server 发送 SYN+ACK 就一直得不到回复。想到的就是重试,但是不能连续快速重试多次,假设 client 掉线了,你总得给它点时间恢复吧,所以呢需要慢慢重试,阶梯性重试。
在 Linux 中就是默认重试5次,并且就是阶梯性的重试,间隔就是1s、2s、4s、8s、16s,再第五次发出之后还得等 32s 才能知道这次重试的结果,所以说总共等63s 才能断开连接。

SYN Flood 攻击有听过吗?

SYN 超时需要耗费服务端 63s 的时间断开连接,也就说 63s 内服务端需要保持这个资源,所以不法分子就可以构造出大量的 client 向 server发 SYN 但就是不回 server。

使得 server 的 SYN 队列耗尽,无法处理正常的建连请求。
所以怎么办?
可以开启 tcp_syncookies,那就用不到 SYN 队列了。SYN 队列满了之后 TCP 根据自己的 ip、端口、然后对方的 ip、端口,对方 SYN 的序号,时间戳等一波操作生成个特殊的序号(即 cookie)发回去,如果对方是正常的 client 会把这个序号发回来,然后 server 根据这个序号建连。
或者调整 tcpsynackretries 减少重试的次数,设置 tcpmaxsyn_backlog 增加 SYN 队列数,设置tcp_abortonoverflow SYN 队列满了直接拒绝连接。

说说 TCP 的四次挥手?

image-20240807111939389

当一个方向另一个方向发送了最后一个数据包后,它会发送一个FIN(结束)消息,收到FIN消息的一方会发送个ACK(确认)消息确认收到FIN消息,然后等待对方的ACK消息。当双方都发送了FIN和ACK消息后,连接被关闭。

为什么要四次挥手?

因为 TCP 是全双工协议,也就是说双方都要关闭,每一方都向对方发送 FIN 和回应ACK。
就像我对你说我数据发完了,然后你回复好的你收到了。然后你对我说你数据发完了,然后我向你回复我收到
了。所以看起来就是四次。
从图中可以看到主动关闭方的状态是 FINWAIT1到 FINWAIT2 然后再到 TIMEWAIT,而被动关闭方是 CLOSEWAIT到 LAST ACK。

挥手一定需要四次吗?

假设 client 已经没有数据发送给 server 了,所以它发送 FIN 给 server 表明自己数据发完了,不再发了,如果这时候 server 还是有数据要发送给 client 那么它就是先回复 ack,然后继续发送数据。
等 server 数据发送完了之后再向 client 发送 FIN 表明它也发完了,然后等 client 的 ACK 这种情况下就会有四次挥手。
那么假设 client 发送 FIN 给 server 的时候 server 也没数据给 cient,那么 server 就可以将 ACK 和它的 FIN 一起发给client ,然后等待 client的 ACK,这样不就三次挥手了?

为什么要有 TIME_WAIT?

断开连接发起方在接受到接受方的 FIN 并回复 ACK之后并没有直接进入 CLOSED 状态,而是进行了一波等待等待时间为 2MSL。
MSL是 Maximum Segment Lifetime,即报文最长生存时间,RFC 793 定义的 MSL 时间是2分钟,Linux 实际实现是 30s,那么 2MSL是一分钟。
那么为什么要等 2MSL呢?
就是怕被动关闭方没有收到最后的 ACK,如果被动方由于网络原因没有到,那么它会再次发送 FIN, 此时如果主动关闭方已经 CLOSED 那就傻了,因此等一会儿。
假设立马断开连接,但是又重用了这个连接,就是五元组完全一致,并且序号还在合适的范围内,虽然概率很低但理论上也有可能,那么新的连接会被已关闭连接链路上的一些残留数据干扰,因此给予一定的时间来处理一些残留数据。

超时重传机制是为了解决什么问题?

提到 TCP 要提供可靠的传输,那么网络又是不稳定的如果传输的包对方没收到却又得保证可靠那么就必须重传。
TCP 的可靠性是靠确认号的,比如我发给你1、2、3、4这4个包,你告诉我你现在要5那说明前面四个包你都收到了,就是这么回事儿。
不过这里要注意,SeqNum 和 ACK 都是以字节数为单位的,也就是说假设你收到了1、2、4 但是3没有收到你不能 ACK 5,如果你回了5 那么发送方就以为你5之前的都收到了。
所以只能回复确认最大连续收到包,也就是 3。
而发送方不清楚 3、4 这两个包到底是还没到呢还是已经丢了,于是发送方需要等待,这等待的时间就比较讲究了。
如果太心急可能 ACK已经在路上了,你这重传就是浪费资源了,如果太散漫,那么接收方急死了,这死鬼怎么还不发包来,我等的花儿都谢了。
所以这个等待超时重传的时间很关键,怎么搞?聪明的小伙伴可能一下就想到了,你估摸着正常来回一趟时间是多少不就好了,我就等这么长。
这就来回一趟的时间就叫 RTT,即 Round Trip Time,然后根据这个时间制定超时重传的时间 RTO,即Retransmission Timeout.

为什么还需要快速重传机制?

超时重传是按时间来驱动的,如果是网络状况真的不好的情况,超时重传没问题,但是如果网络状况好的时候只是恰巧丢包了,那等这么长时间就没必要。
于是又引入了数据驱动的重传叫快速重传,什么意思呢?就是发送方如果连续三次收到对方相同的确认号,那么马上重传数据。
因为连续收到三次相同 ACK 证明当前网络状况是 ok的,那么确认是丢包了,于是立马重发,没必要等这么久。

SACK 的引入是为了解决什么问题?

SACK 即 Selective Acknowledgment,它的引入就是为了解决发送方不知道该重传哪些数据的问题我们来看下面的图就知道了。

image-20240807150112699

SACK 就是接收方会回传它已经接受到的数据,这样发送方就知道哪一些数据对方已经收到了,所以就可以选择性的发送丢失的数据。
如图,通过 ACK 告知我接下来要 5500 开始的数据,并一直更新 SACK,6000-6500 我收到了,6000-7000的数据我收到了,6000-7500的数据我收到了,发送方很明确的知道,5500-5999的那一波数据应该是丢了,于是重传。
而且如果数据是多段不连续的,SACK 也可以发送,比如 SACK0-500,1000-1500,2000-2500。就表明这几段已经收到了。

D-SACK 其实是 SACK 的扩展,它利用 SACK 的第一段来描述重复接受的不连续的数据序号,如果第一段描述的范围被 ACK 覆盖,说明重复了,比如我都 ACK 到6000了你还给我回 SACK 5000-5500 呢?
说白了就是从第一段的反馈来和已经接受到的 ACK比一比,参数是 tcp_dsack,Linux 2.4之后默认开启。
那知道重复了有什么用呢?
1)知道重复了说明对方收到刚才那个包了,所以是回来的 ACK 包丢了。
2)是不是包乱序的,先发的包后到?
3)是不是自己太着急了,RTO 太小了?
4)是不是被数据复制了,抢先一步呢?

滑动窗口的作用是什么?

TCP 有序号,并且还有重传,但是这还不够,还需要根据情况来控制一下发送速率,因为网络是复杂多变的,有时候就会阻塞住,而有时候又很通畅。
所以发送方需要知道接收方的情况,好控制一下发送的速率,不至于蒙着头一个劲儿的发然后接受方都接受不过来。
因此 TCP 就有个叫滑动窗口的东西来做流量控制,也就是接收方告诉发送方我还能接受多少数据,然后发送方就可以根据这个信息来进行数据的发送,
以下是发送方维护的窗口,就是黑色圈起来的。image-20240807151407392

image-20240807151327175

已经有滑动窗口了为什么还要拥塞控制?

加了拥塞控制是因为 TCP 不仅仅就管两端之间的情况,还需要知晓一下整体的网络情形,毕竟只有大家都守规矩了道路才会通畅。
前面我们提到了重传,如果不管网络整体的情况,肯定就是对方没给 ACK,那我就无脑重传。如果此时网络状况很差,所有的连接都这样无脑重传,是不是网络情况就更差了,更加拥堵了,所以需要个拥塞控制,来避免这种情况的发送。

说说拥塞控制的步骤?

主要有以下几个步骤来搞:
1)慢启动,探探路。
2)拥塞避免,感觉差不多了减速看看
3)拥塞发生快速重传/恢复

image-20240807152255383

慢启动,就是新司机上路慢慢来,初始化cwnd(Congestion Window)为1,然后每收到一个 ACK 就 cwnd++并且每过一个RTT,cwnd=2*cwnd。
线性中带着指数,指数中又夹杂着线性增。
然后到了一个阈值,也就是 ssthresh(slow start threshold)的时候就进入了拥塞避免阶段。
这个阶段是每收到一个 ACK 就 cwnd= cwnd + 1/cwnd并且每-个 RTT 就 cwnd++。
可以看到都是线性增。
然后就是一直增,直到开始丢包的情况发生,前面已经分析到重传有两种,!,一种是超时重传,一种是快速重传。
如果发生超时重传的时候,那说明情况有点糟糕,于是直接把 ssthresh 置为当前 cwnd 的一半,然后 cwnd 直接变为 1,进入慢启动阶段。
如果是快速重传,那么这里有两种实现,一种是 TCP Tahoe ,和超时重传一样的处理。
一种是 TCP Reno,这个实现是把 cwnd=cwnd/2 ,然后把 ssthresh 设置为当前的 cwnd
然后进入快速恢复阶段,将cwnd= cwnd+3(因为快速重传有三次),重传 DACK指定的包,如果再收到一个DACK则 cwnd++,如果收到是正常的 ACK 那么就将 cwnd 设为 ssthresh 大小,进入拥塞避免阶段。
可以看到快速恢复就重传了指定的一个包,那有可能是很多包都丢了,然后其他的包只能等待超时重传,超时重传就会导致 cwnd 减半,多次触发就指数级下降。
所以又搞了个 New Reno,多加了个New,它是在没有SACK的情况下改进快速恢复,它会观察重传 DACK 指定的包的响应 ACK 是否是已,经发送的最大 ACK,比如你发了1、2、3、4,对方没收到 2,但是 3、4都收到了,于是你重传 2 之后 ACK 肯定是 5,说明就丢了这一个包。
不然就是还有其他包丢了,如果就丢了一个包就是之前的过程一样,如果还有其他包丢了就继续重传,直到 ACK是全部的之后再退出快速恢复阶段。
简单的说就是一直探测到全部包都收到了再结束这个环节。
还有个 FACK,它是基于 SACK 用来作为重传过程中的拥赛控制,相对于上面的 New Reno 我们就知道它有 SACK所以不需要一个一个试过去。

ARP 和 RARP 分别是什么?有什么区别?

ARP(Address Resolution Protocol)将IP 地址转换为 MAC 地址,因为最终需要找到 MAC 地址才能跟具体的设
备通信。而 RARP(Reverse Address Resolution Protocol)用于将 MAC 地址转换为IP 地址,比如一些设备启动的时候,需要根据 RARP 来得知分配给它的ip 是什么。

ARP协议的工作原理
1.获取目标设备的IP地址,
2.检查自己的ARP缓存表,如果查到了对应的MAC地址,则直接发送数据包.
3.发送ARP请求,包含自己的IP地址,MAC地址,以及需要解析的IP地址,广播到局域网中所有设备。
4.目标收到ARP请求后,首先会检查请求的IP地址是否与自己的IP地址匹配,如匹配,则创建ARP响应消息,将自己的IP地址及对应的MAC地址返回给请求方。
5.当ARP请求方收到了ARP响应,会更新自己的ARP缓存,将目标IP及对应的MAC写入ARP缓存表:

TCP/IP 四层模型是什么?

四层主要指的是:网络接口层、互联网层、传输层和应用层。
网络接口层负责在计算机和网络硬件之间传输数据
互联网层(网络层)通过IP 协议提供数据包的路由和转发
传输层通过 TCP 和 UDP 协议提供端到端的通信服务
应用层通过各种协议提供网络应用程序的功能,如 HTTP等

七层模型是什么?

OSI七层模型是计算机网络通信的标准模型,从底层到顶层依次为:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。
1)物理层,主要描述物理层面的传输,比如光纤、电缆
2)数据链路层,可以认为是 MAC 层面相邻节点的传输。
3)网络层,IP 层面的寻址、路由。
4)传输层,TCP 和 UDP 层的传输
5)会话层,负责会话状态的保持、管理与同步,
6)表示层,些数据的转化,压缩和编码,
7)应用层,http 之类的协议的交互转化:

Cookie、Session、Token 之间有什么区别?

Cookie 存储在浏览器,生命周期可以由服务器端设置。
Session 存储在服务器,生命周期由服务器端控制。
Token(如JWT)存储在客户端,是一个加密的令牌,可以跨多个会话使用。
简单来说,Cookie 和Session 更适合用于单次会话的认证和状态管理,而 Token 更适合用于跨会话的认证和状态管理。

JWT Token 听过吗?

Token(如JWT)其实就是一个加密的令牌,服务端通过一定的方式将用户的信息加密生成一个JT Token,后续客户端带着这个 token 来访问服务端时,服务端可以解密得到对应的用户信息,这样就能进行身份和权限的验证了。

当你在浏览器输入一个域名回车后,会发生什么?

请求将域名解析为对应的IP 地址。DNS 服务器返回简单流程如下:浏览器会向DNS服务器发送一个查询请求,IP 地址后,浏览器使用该IP 地址向服务器发起 HTTP 请求。
服务器收到请求后,做对应的处理,且返回相应的网页内容。浏览器接收到网页内容后,解析 HTML、CSSJavaScript 等文件,最终显示网页
整个过程涉及到 DNS 解析、HTTP 请求、服务器响应和浏览器解析等步骤。

简单谈谈你对 CDN 的理解?

CDN(Content Delivery Network)是一种分布式网络架构,用于加速互联网内容的分发
因为网络传输有距离限制,部署杭州的服务器,不同地区的用户访问得到响应的时长是不一样的,杭州的用户来访问肯定比美国的用户来访问快多了。
所以就弄了个 CDN 来加快内容的分发:
它通过在全球多个地理位置部署服务器,当用户请求内容时,CDN 会根据用户的地理位置,将请求转发到最近的缓存服务器上。这样可以减少数据传输的延迟,提高用户访问速度,同时减轻源服务器的负载。
CDN 通常用于加速静态内容(如图片、视频、静态页面等)的访问,提高网站的性能和用户体验。

简单谈谈你对 DNS 的理解?

DNS(Domain Name System)是一个用于将域名转换为IP 地址的分布式数据库系统
它的工作原理是,当用户输入一个域名时,DNS 服务器会查询该域名对应的IP 地址,并将结果返回给用户。这样,用户就可以通过域名访问网站,而不需要记住复杂的IP地址。DNS 的使用简化了网络访问过程,提高了网络通信的效率。


计算机网络知识复习
https://zzy-1128.github.io/2024/08/07/计算机网络知识复习/
Author
智勇爱学习
Posted on
August 7, 2024
Licensed under