4、网络
技术栈:
1、计算机网络体系结构
OSI分层 (7层):物理层、数据链路层(网桥,交换机)、网络层(IP,ICMP,ARP)、传输层(TCP,UDP)、会话层、表示层、应用层。
TCP/IP分层(4层):网络接口层、 网际层、运输层、 应用层。
五层协议 (5层):物理层、数据链路层、网络层、运输层、 应用层。
2、ARP是地址解析协议,简单语言解释一下工作原理
ARP 实现由 IP 地址得到 MAC 地址
主机A广播发送ARP请求分组(源主机IP地址,源主机MAC地址,目的主机的IP地址)
主机B向A发送ARP响应分组(源主机IP地址,源主机MAC地址)
1:首先,每个主机都会在自己的ARP缓冲区中建立一个ARP列表,以表示IP地址和MAC地址之间的对应关系。
2:src发送:
当源主机要发送数据时,首先检查ARP列表中是否有对应IP地址的目的主机的MAC地址
如果有,则直接发送数据;
如果没有,就向本网段的所有主机发送ARP数据包,该数据包包括的内容有:源主机IP地址,源主机MAC地址,目的主机的IP地址。
3:dst接受:
当本网络的所有主机收到该ARP数据包时:
首先检查数据包中的IP地址是否是自己的IP地址,如果不是,则忽略该数据包;
如果是,则首先从数据包中取出源主机的IP和MAC地址写入到ARP列表中,如果已经存在,则覆盖,然后将自己的MAC地址写入ARP响应包中,告诉源主机自己是它想要找的MAC地址。
4:dst发送:
源主机收到ARP响应包后。将目的主机的IP和MAC地址写入ARP列表,并利用此信息发送数据。
如果源主机一直没有收到ARP响应数据包,表示ARP查询失败。
3、TCP
是一种面向连接的、可靠的、基于字节流的传输层通信协议
(1)可靠性保证:
-
数据包校验:目的是检测数据在传输过程中的任何变化,若校验出包有错,则丢弃报文段并且不给出响应,这时TCP发送数据端超时后会重发数据;
-
对失序数据包重排序:既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。TCP将对失序数据进行重新排序,然后才交给应用层;
-
丢弃重复数据:对于重复数据,能够丢弃重复数据;
-
应答机制:当TCP收到发自TCP连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒;
-
超时重发:当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段;
-
流量控制:TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据,这可以防止较快主机致使较慢主机的缓冲区溢出,这就是流量控制。TCP使用的流量控制协议是可变大小的滑动窗口协议。
(2)滑动窗口
TCP由于存在确认应答机制,在一方发出一条消息以后,另一方要发送ACK表明自己收到消息。
如果按照下面这种形式,每次收到ACK才发出下一条消息,这种一发一收的效率太低。但是如果客户端不急着接收ACK,可以利用等待ACK的空挡直接发送下一批数据,这样就可以做到短时间内发送多批数据。这就是滑动窗口的基本思想。
滑动窗口可能出现的状况:
(1)中间报文丢了
假设客户端依次发送1001-2000,2001-3000,3001-4000
客户端如果连续多次(一般是连续三次)收到了2001的确认应答,说明序号为2001之后的报文丢了,此时就会重传2001~3000的报文;服务端收到2001~3000的报文以后,由于之前已经收到了3001~4000 的报文(暂时存放在接收缓冲区),那么服务端相当于已经收到了全部的报文,此时服务端发送的确认序号是 4001,表明4001之前的报文已经全部收到(4001+ACK)
(2)后发送的报文先收到了ACK
原因:要么丢了 要么网络延时到达
如果开了sack选项(net.ipv4.tcp_sack),表示会选择性地重传未回ACK的报文;否则,会重传开始丢失的报文段之后的所有报文
(3)滑动窗口大小为0时,何时才能继续发送数据?
原因:对方上层的处理速度较慢,导致对方接收缓冲区里的数据没有被取走
解决方法:
a、发送方定期发送不携带数据的报文
发送方定期可以发送一个不携带数据的报文,报文不携带数据,也就不会占用服务端的缓冲区,接收方返回的ACK中会携带窗口大小,以此来判断是否可以继续发送数据。
b、接收方缓冲区一旦更新立马通知发送方
接收方的上层把数据取走的时候,服务端主动发送一个窗口更新的通知报文,该报文不携带任何数据,只是在报文首部设置了16位窗口大小
(3)拥塞控制:
1、慢启动
由小到大逐渐增加拥塞窗口的大小
2、拥塞避免
让拥塞窗口缓慢增长,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍,这样拥塞窗口按线性规律缓慢增长
设置一个慢开始门限 ssthresh,当 cwnd >= ssthresh 时,进入拥塞避免,每个轮次只将 cwnd 加 1
如果出现了超时,则令 ssthresh = cwnd / 2,然后重新执行慢开始
3、快重传
在接收方,要求每次接收到报文段都应该对最后一个已收到的有序报文段进行确认。如果收到三个重复确认,那么可以知道下一个报文段丢失,此时执行快重传,立即重传下一个报文段。
例如已经接收到 M1 和 M2,此时收到 M4,应当发送对 M2 的确认;收到三个 M2,则 M3 丢失,立即重传 M3
4、快恢复
当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把ssthresh门限减半,但是接下去并不执行慢开始算法
4、TCP 三次握手
客户端A 服务端B
(1)A向B发送请求报文,SYN=1,ACK=0,选择一个初始序号seq=x。
(2)B 收到连接请求报文,如果同意建立连接,则向 A 发送连接确认报文,SYN=1,ACK=1,确认号为ack= x+1,同时也选择一个初始的序号 seq=y。
(3)A 收到 B 的连接确认报文后,还要向 B 发出确认,确认号为ack= y+1,序号为 seq=x+1。
B 收到 A 的确认后,连接建立。
5、TCP四次挥手
客户端A 服务端B
(1)A 发送连接释放报文,FIN=1(表明此报文段的发送方的数据已发送完毕,并要求释放运输连接)。
(2)B 收到之后发出确认,此时 TCP 属于CLOSE-WAIT状态,让服务器端发送还未传送完毕的数据,即B 能向 A 发送数据但是 A 不能向 B 发送数据。
(3)当 B 不再需要连接时,发送连接释放报文,FIN=1。
(4)A 收到后发出确认,进入 TIME-WAIT 状态,等待 2 MSL(最大报文存活时间)后释放连接。
cat /proc/sys/net/ipv4/tcp_fin_timeout -> 60s
-
B 收到 A 的确认后释放连接。
为什么A在TIME-WAIT状态必须等待2MSL的时间呢?
为了保证A发送的最后一个ACK报文段能够到达B;
防止“已经失效的连接请求报文段”出现在本链接中。
为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了
问题定位思路:
参考链接:
计算机网络面试题(一) - 知乎