Interview_计网_day19
计网学习资料
可以看看概论的 \(OSI\) 参考模型,传输层,应用层部分。
\(IP\) 地址和 \(MAC\) 地址
- \(MAC\) 地址是物理地址,用来定位网络设备的位置,不可改变,使用在数据链路层。
- \(IP\) 地址是虚拟地址,为互联网上每一个网络和主机分配一个逻辑地址,可以动态变化,使用在网络层。
\(IP\) 层怎么知道报文给哪个应用程序。如何区分 \(TCP\) 和 \(UDP\) 报文
- 通过端口号区分。
- 通过 \(IP\) 数据报首部中的协议标识符字段区分。\(UDP\) 是 \(17\),\(TCP\) 是 \(6\)。
\(TCP\) 和 \(UDP\) 区别/应用场景
区别:
- 连接
- \(TCP\) 是 面向连接 的通信,传输数据前必须建立连接。
- \(UDP\) 是 无连接 的通信,传输数据前不用建立连接。
- 服务对象
- \(TCP\) 的每一条连接是 一对一 的。
- \(UDP\) 的连接支持 一对一、一对多、多对一、多对多 的通信。
- 可靠性和效率
- \(TCP\) 提供 可靠的服务,保证数据无差错、无丢失、不重复、按序到达。但传输速度慢。
- \(UDP\) 尽最大努力交付,不保证可靠交付。但传输速度快。
- 数据报长度
- \(TCP\) 数据报是动态长度的,报文长度根据 接收方窗口大小 和 网络拥塞情况 动态决定。
- \(UDP\) 是面向报文的,对于上面传下来的数据报,添加首部后就交给网络层。不合并,不拆分,保留这些报文的边界。
- 首部开销
- \(TCP\) 首部开销大,首部固定 \(20\) 字节 + 选项(长度可变,最短 \(0\) 字节,最长 \(40\) 字节)
- \(UDP\) 首部开销小,首部固定 \(8\) 字节。
- 资源要求
- \(TCP\) 对系统资源要求多。
- \(UDP\) 对系统资源要求少。
应用场景:
- 若保证 数据完整性 更重要的话,使用 \(TCP\) 协议,例如文件传输。
- 若保证 数据实时性 更重要的话,使用 \(UDP\) 协议,例如 \(QQ\) 聊天、在线视频 (即时通信,速度要求高,但偶尔的间断不是问题)。
\(TCP\) 首部报文
(图片来自 https://blog.csdn.net/qq_32998153/article/details/79680704)
- 源端口、目的端口:通信发送方和接收方的端口。
- 序号:本报文段中第一个数据节点的序号。
- 确认号:下一个报文段希望收到的第一个数据节点的序号。
- 数据偏移:指出数据部分和报文起始处的距离。
- \(6\) 个控制位
- \(URG\):紧急位,表示有一个紧急数据需要尽快发送,而不是在发送缓存中排队等待。
- \(ACK\):确认位,当 \(ACK=1\) 时,确认号才有意义。
- \(PSH\):推送位,表示有一个紧急数据需要尽快交付给应用进程,而不是在接收缓存中等待。
- \(RST\):复位位,表示 \(TCP\) 传输过程中出现了严重错误,需要释放连接,然后重新建立连接。
- \(SYN\):同步位,在建立连接时用来同步序号。
- \(FIN\):终止位,当 \(FIN=1\) 时,表示数据传输完成,想要释放连接。
- 窗口:作为接收方让发送方设置其发送窗口的依据。
- 检验和:检验数据是否发生错误。
- 紧急指针:在 \(URG=1\) 时使用,表示本报文段中紧急数据的字节数。
- 选项:长度可变,最长可以有 \(40\) 字节
\(TCP\) 如何保证可靠性
- 检验和
- 发送方在发送数据之前计算检验和并取反,填入数据报中检验和位置。
- 接收方接收数据报后,再次将所有数据求和并取反,如果得到的结果是全 \(0\) 的,则说明没有发生错误。
- 序列号
- \(TCP\) 为每个字节的数据都进行了编号,这就是序列号。
- 序列号保证了 \(TCP\) 传输的可靠性和数据的有序到达,提高了效率、去除了重复数据。
- 确认应答
- 接收方每次收到数据后,都会进行确认,发送 \(ACK\) 报文,其中的确认号告诉发送方接收到了哪些数据,希望下一次从哪里开始发。
- 超时重传
- 发送方发送数据后,如果一直没有等到确认报文,则认为数据丢失,则会重新发送数据。
- 等待的时间通过 \(RTTs\) 计算,\(NewRTTs = (1- \alpha)*OldRTTs + \alpha*SampleRTTs\),\(\alpha\) 取值一般为 \(0.125\)。
- 连接管理
- 三次挥手、四次握手
- 流量控制
- 拥塞控制
- 与流量控制不同的点在于,流量控制是对发送方和接收方之间的调节,拥塞控制是对整个网络全局性的调节。
\(TCP\) 流量控制
如果发送方发送数据太快,接收方来不及接收,可能使数据丢失。流量控制就是用来控制发送方的发送速度的。
\(TCP\) 的流量控制通过 滑动窗口 来实现,发送方窗口不可以超过接收方窗口大小。
接收方每次收到数据报后,在确认报文的窗口位置告诉对方自己的窗口大小,发送方收到确认报文以后,调整自己的窗口大小。
如果接收方再一次确认报文中,将窗口设为了 \(0\),那么发送方就停止发送,直到接收方在发送一个确认报文,重新设置窗口值后,才可以继续发送。
如果接收方重新设置窗口值的报文丢失,发送方等了很久都没有收到,这就会陷入一个僵局。当然发送方也有打破僵局的方法,发送方定时发送一个 测试报文,询问接收方是否可以继续发送,如果可以,接收方就会告诉发送方此时它可以接收的窗口大小。如果不可以,发送方就继续等待,重置定时器。
\(TCP\) 拥塞控制
当过多数据注入到网络中,使网络中的 对资源的需求>可提供资源 时,这就是网络拥塞。
\(TCP\) 的拥塞控制方法有四种:慢开始、拥塞避免、快重传、快恢复。发送双方都有一个拥塞窗口 \(cwnd\)。
(图片来自 https://blog.csdn.net/m0_37962600/article/details/79993310)
- 慢开始和拥塞避免
- 最开始的时候,由于不清楚网络的情况,所以发送方最开始的拥塞窗口为 \(1\),每经过一个往返时间 \(RTT\),\(cwnd\) 翻倍。当 \(cwnd\) 超过慢开始门限以后,则使用拥塞避免算法。
- 为了使 \(cwnd\) 缓慢的增大,每经过一个 \(RTT\),\(cwnd\) 增长 \(1\)。在这过程中,一旦发生网络拥塞,则将慢开始门限设为当前值的一半,并重新设置 \(cwnd\) 为 \(1\),重新启动慢开始。
- 快重传和快恢复
- 快重传要求在收到一个失序的报文段后就立即发送重复确认,发送方只要连续收到三个重复的确认,就认为这个报文段丢失,然后立即重传。
- 当发送方连续收到了三个重复确认,就乘法减半,慢开始门限设置为当前值的一半,\(cwnd\) 设置为现在的慢开始门限,然后进行拥塞避免算法。
\(TCP\) 三次握手
(图片来自 https://blog.51cto.com/fengbaoli/1782250)
\(seq:\) 序号,\(ack:\) 确认号
- \(Round\ 1:\) 客户端发送连接建立请求报文段,无应用层数据。
- \(Round\ 2:\) 服务器端为该 \(TCP\) 连接分配缓存和变量,并向客户端发送确认报文端,允许连接,无应用层数据。
- \(Round\ 3:\) 客户端为该 \(TCP\) 连接 分配缓存和变量,并向服务器端发送确认的确认,此时可以携带数据。
三次握手的目的是:连接服务器指定端口,建立 \(TCP\) 连接,同步连接双方的序列号和确认号,交换 \(TCP\) 窗口大小信息。
为什么需要回传 \(SYN\)
为了告诉发送端我收到的信息是你发送的请求建立连接的信号。
已经传了 \(SYN\),为什么需要传 \(ACK\)
为了确保通信双方无误,传了 \(SYN\) 代表发送方到接收方的信号没问题,传 \(ACK\) 为了确认接收方到发送方的信号没问题。
\(TCP\) 为什么不可以两次握手
假设只有两次握手,一开始客户端向服务器端发送了第一个请求建立连接的信息,但这时由于网络拥塞,信息迟迟没有到底服务器端。
客户端没有等待服务器端发来的确认信息,则又发送了第二个请求建立连接的信息并正确建立了 \(TCP\) 连接,于是客户端和服务端开始了正常的数据传输。
直到数据传输完成,关闭连接后。第一个迟到的连接到达服务器端,服务器端认为客服换又想和我建立连接,于是同意了连接,并开始等待客户端发送数据,然后对于客户端来说,并没有发送新的请求,则会丢弃服务器的信息,那么服务器端就会一直处于等待状态,造成资源的浪费。
\(TCP\) 为什么不用四次握手
经过三次握手以后,客户端和服务器端都确定了自己能够得到对方的信息,也确定了自己发送的信息对方可以收到,那么就不需要多余的第四次了。
\(TCP\) 四次挥手
(图片来自 https://blog.51cto.com/fengbaoli/1782250)
- \(Round\ 1:\) 客户端发送连接释放报文段,停止发送数据,主动关闭 \(TCP\) 连接。
- \(Round\ 2:\) 服务器端回送一个确认报文段,此时客户端到服务器的连接已经释放了,处于 半关闭状态。此时如果服务器端有数据想要发给客户端,客户端仍然要接收。
- \(Round\ 3:\) 服务器端发完数据以后,发送连接释放报文段,主动关闭 \(TCP\) 连接
- \(Round\ 4:\) 客户端回复一个确认报文段,等待 \(2MSL\) 后,连接彻底关闭
\(TCP\) 四次挥手中 \(TIME\_WAIT\) 为什么要等待 \(2MSL\)
- 原因 \(1:\) 保证最后一个 \(ACK\) 报文段能够到达 \(B\)。假如这个报文段丢失,服务器端没有收到 \(ACK\) 报文段,就会认为自己的 \(FIN\) 报文段可能在中途丢失,于是再发送一遍,如果客户端没有等待 \(2MSL\) 而提早关闭,就会收不到这个报文段,自然也不会发出 \(ACK\) 报文段,这样使得服务器端一直处于等待状态,造成资源浪费。
- 原因 \(2:\) 在 \(A\) 发送最后一个 \(ACK\) 报文段后,在经过 \(2MSL\) 时间,就可以使本次连接持续时间内产生的所有报文段都从网络中消失了。这样可以使下一次建立连接的时候不会有上一次残留的报文段。
\(TIME\_WAIT\) 状态危害
每一个连接都要占用一个文件描述符,但系统的文件描述符是有限的,所以如果 \(TIME\_WAIT\) 状态的连接太多,就会导致可用连接减少。
如何避免 \(TIME\_WAIT\)
可以设置 \(SO\_REUSEADDR\) 套接字选项。
这么做的目的是通知操作系统,如果端口忙且 \(TCP\) 连接位于 \(TIME\_WAIT\) 状态时可以重用端口。