TCP/UDP的常见面经问题
# TCP连接的建立过程
1. 三次握手
为什么要进行三次握手。
握手是为了让双方了解数据开始时的序列号,而三次是让双方达成共识的最小次数
三次握手的过程:
1. 客户端发送(SYN=1,ISN=A);//SYN_SEND
2. 服务端发送(ACK=1,SYN=1),(ack=A+1,ISN=B);//这个时候服务端知道了客户端的序列号,并且通知客户端这个事实。
3. 客户端发送(ack=B+1,seq=A+1);//SYN-SEND->ESTABLISHED,通知服务端,客户端已经了解了服务端的序列号。
三次握手结束后,客户端和服务端都保证了双方相互知道了自己的序列号,也就是数据传输的起点。
如果进行两次握手:
1. 客户端(连接主动方)传递(SYN=1,ACK=0,seq=A);
2. 服务端返回(SYN=1,ACK=1,ack=A+1,seq=B)
这时结束,那么只有客户端被通知了自己的信息已经被服务端知晓,但是服务端却无法知道自己的序列号是否被客户端知晓。
如果进行四次握手
1. 客户端:(SYN=1, ISN=A)
2. 服务端:(ACK=1, ack=A+1)
3. 服务端:(SYN=1, ISN=B)
4. 客户端(ACK=1,ack=B+1)
明显2和3可以重合。
半连接:服务器没有收到客户端的回应,无法从SYN-RECEIVE->ESTABLISH
1. 可能是服务端的SYN-ACK丢失了。
2. 可能是客户端的ACK丢失了。
这时,服务端会维护一个半连接的队列,等待超时重传。
2. 四次挥手
假设是客户端主动放弃连接
1. 客户端:发送FIN // FIN_WAIT
2. 服务端:发送ACK //CLOSE_WAIT,这时,客户端了解服务端已经关闭了连接
3. 服务端:发送FIN //LAST_ACK
4. 客户端:发送ACK //TIME_WAIT->(After 2MSL)CLOSE
半打开和半关闭:
半打开:连接中有一端的突然关闭
半关闭:
A发送FIN,B收到后发送ACK,但是B不继续发送FIN,导致A无法完全关闭连接。
为什么要等待2MSL
1. 防止服务端没有收到ACK
2. 等待网络中的重复数据的消失(MSL:MAX SEGMENT LIFETIME)
# TCP的Congestion Control
TCP通过两种方式来判断传输环境,Duplicate ACK和Time Out。当发生Duplicate ACK的时候,说明传输过程中,有个别的报文没有达到目的地,需要重新发送。 如果发生Time Out,说明网络环境非常差。
TCP在控制阻塞窗口的时候有两个重要参数,ssthresh(门槛),cwnd(窗口大小)。
当TCP处于Slow Start阶段时:
每收到一个ACK,cwnd指数增加,也就是 cwnd = (1,2,4,8.....)。
当cwnd > ssthresh,cwnd变成线性增加,也就是进入Congestion Control阶段。
当发生Timeout或者DuplicateACK时,
1. 如果使用的是Tahoe:cwnd=1,ssthresh=cwnd/2。
2. 如果使用的是Reno且是DuplicateACK时,cwnd=cwnd/2,也就是说,没有慢启动阶段,直接过度到Congestion Control。
滑动窗口
TCP连接通过控制滑动窗口的大小来控制传输速率。根据网络状况,滑动窗口的大小会有变化。