C++面试题汇总 计算机网络

TCP怎么保证可靠性,并且简述一下TCP建立连接和断开连接的过程

  • TCP保证可靠性:
    • 序列号确认应答超时重传
      • 数据到达接收方,接收方需要发出一个确认应答,表示已经收到该数据段,并且确认序号会说明了它下一次需要接收的数据序列号
      • 如果发送发迟迟未收到确认应答,那么可能是发送的数据丢失,也可能是确认应答丢失,这时发送方在等待一定时间后会进行重传。
      • 这个时间一般是2*RTT(报文段往返时间) + 一个偏差值
    • 窗口控制高速重发控制/快速重传(重复确认应答)
      • TCP会利用窗口控制来提高传输速度,意思是在一个窗口大小内,不用一定要等到应答才能发送下一段数据,窗口大小就是无需等待确认而可以继续发送数据的最大值
      • 如果不使用窗口控制,每一个没收到确认应答的数据都要重发。使用窗口控制,如果数据段1001-2000丢失,后面数据每次传输,确认应答都会不停地发送序号为1001的应答,表示我要接收1001开始的数据,发送端如果收到3次相同应答,就会立刻进行重发
      • 但还有种情况有可能是数据都收到了,但是有的应答丢失了,这种情况不会进行重发,因为发送端知道,如果是数据段丢失,接收端不会放过它的,会疯狂向它提醒
    • 拥塞控制
      • 如果把窗口定的很大,发送端连续发送大量的数据,可能会造成网络的拥堵,甚至造成网络的瘫痪。所以TCP在为了防止这种情况而进行了拥塞控制。
      • 慢启动:定义拥塞窗口,一开始将该窗口大小设为1,之后每次收到确认应答(经过一个RTT),将拥塞窗口大小*2
      • 拥塞避免:设置慢启动阈值,一般开始都设为65536。拥塞避免是指当拥塞窗口大小达到这个阈值,拥塞窗口的值不再指数上升,而是加法增加(每次确认应答/每个RTT,拥塞窗口大小+1),以此来避免拥塞。
      • 将报文段的超时重传看做拥塞,则一旦发生超时重传,我们需要先将阈值设为当前窗口大小的一半,并且将窗口大小设为初值1,然后重新进入慢启动过程。
      • 快速重传:在遇到3次重复确认应答(高速重发控制)时,代表收到了3个报文段,但是这之前的1个段丢失了,便对它进行立即重传(而不必继续等待设置的重传计数器时间到期)。然后,先将阈值设为当前窗口大小的一半,然后将拥塞窗口大小设为慢启动阈值+3的大小
        • 这样可以达到:在TCP通信时,网络吞吐量呈现逐渐的上升,并且随着拥堵来降低吞吐量,再进入慢慢上升的过程,网络不会轻易的发生瘫痪。

  • 参考: TCP 慢启动,拥塞避免,快速重传,快速恢复
  • 慢启动
    • 定义拥塞窗口,一开始将该窗口大小设为1,之后每次收到确认应答(经过一个RTT),将拥塞窗口大小*2
  • 拥塞避免
    • 设置慢启动阈值,一般开始都设为65536。拥塞避免是指当拥塞窗口大小达到这个阈值,拥塞窗口的值不再指数上升,而是加法增加(每次确认应答/每个RTT,拥塞窗口大小+1),以此来避免拥塞。
  • 快速重传
    • 情况:

      • 遇到3次重复确认应答ACK时,代表接收端收到了3个报文段,但是这之前的1个段丢失了。此时进行快速重传
    • 反应:

      • 便对它进行立即重传(而不必继续等待设置的重传计数器时间到期)
      • 先, 将阈值设为当前窗口大小的一半
      • 然后, 将拥塞窗口大小设为慢启动阈值+3的大小
      • 最后, 重新进入拥塞避免阶段。

      • 后来的“快速恢复”算法是在上述的“快速重传”算法后添加的,当收到3个重复ACK时,TCP最后进入的不是拥塞避免阶段,而是快速恢复阶段。
      • 快速重传和快速恢复算法一般同时使用。
      • 快速恢复的思想是“数据包守恒”原则,即同一个时刻在网络中的数据包数量是恒定的,只有当“老”数据包离开了网络后,才能向网络中发送一个“新”的数据包,如果发送方收到一个重复的ACK,那么根据TCPACK机制就表明有一个数据包离开了网络,于是cwnd1
      • 如果能够严格按照该原则那么网络中很少会发生拥塞,事实上拥塞控制的目的也就在修正违反该原则的地方。

  • 快速恢复:
    • 当收到3个重复ACK时,把阈值设置为当前窗口的一半,把当前窗口设置为阈值的值加3,然后重传丢失的报文段,(加3的原因是因为收到3个重复的ACK,表明有3个“老”的数据包离开了网络)。

    • 再收到重复的ACK时,拥塞窗口增加1

    • 当收到新的数据包的ACK时,把cwnd设置为第一步中的ssthresh的值。原因是因为该ACK确认了新的数据,说明从重复ACK时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态。

    • 快速重传针对的是一个包的重传, 快速恢复针对的是恢复一个窗口内的多个包丢失的情况


      • 但是可以看出Reno的快速重传算法是针对一个包的重传情况的,然而在实际中,一个重传超时可能导致许多的数据包的重传,因此当多个数据包从一个数据窗口中丢失时并且触发快速重传和快速恢复算法时,问题就产生了。
      • 因此NewReno出现了,它在Reno快速恢复的基础上稍加了修改,可以恢复一个窗口内多个包丢失的情况。
      • 具体来讲就是:
        • Reno在收到一个新的数据的ACK时就退出了快速恢复状态了,
        • NewReno需要收到该窗口内所有数据包的确认后才会退出快速恢复状态,从而更一步提高吞吐量。

  • TCP建立连接和断开连接的过程:


    • 序列号seq:占4个字节,用来标记数据段的顺序,

      • TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生;
      • 给字节编上序号后,就给每一个报文段指派一个序号;
      • 序列号seq就是这个报文段中的第一个字节的数据编号。
    • 确认号ack:占4个字节,期待收到对方下一个报文段的第一个数据字节的序号;

      • 序列号表示报文段携带数据的第一个字节的编号;
      • 而确认号指的是期望接收到下一个字节的编号;
      • 因此当前报文段最后一个字节的编号+1即为确认号。
    • 确认ACK:占1位,仅当ACK=1时,确认号字段才有效。ACK=0时,确认号无效

    • 同步SYN:连接建立时用于同步序号。

      • SYN=1ACK=0时表示:这是一个连接请求报文段。
      • 若同意连接,则在响应报文段中使得SYN=1ACK=1
        • 因此,SYN=1表示这是一个连接请求,或连接接受报文。
      • SYN这个标志位只有在TCP建产连接时才会被置1,握手完成后SYN标志位被置0
    • 终止FIN:用来释放一个连接。FIN=1表示:此报文段的发送方的数据已经发送完毕,并要求释放运输连接

    • PS

      • ACKSYNFIN这些大写的单词表示标志位,其值要么是1,要么是0
      • ackseq小写的单词表示序号。

    三次握手和四次握手

    • 三次握手

      • Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给ServerClient进入SYN_SENT状态,等待Server确认。
      • Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYNACK都置为1ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
      • Client收到确认后,
        • 检查ack是否为J+1ACK是否为1,如果正确则将标志位ACK置为1ack=K+1,并将该数据包发送给Server
        • Server检查ack是否为K+1ACK是否为1,如果正确则连接建立成功,
      • ClientServer进入ESTABLISHED状态,完成三次握手,随后ClientServer之间可以开始传输数据了。
    • 四次挥手

      • 由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则 是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了 ,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。
      • 数据传输结束后,客户端的应用进程发出连接释放报文段,并停止发送数据,客户端进入FIN_WAIT_1状态,此时客户端依然可以接收服务器发送来的数据。
      • 服务器接收到FIN后,发送一个ACK给客户端,确认序号为收到的序号+1,服务器进入CLOSE_WAIT状态。客户端收到后进入FIN_WAIT_2状态。
      • 当服务器没有数据要发送时,服务器发送一个FIN报文,此时服务器进入LAST_ACK状态,等待客户端的确认
      • 客户端收到服务器的FIN报文后,给服务器发送一个ACK报文,确认序列号为收到的序号+1。此时客户端进入TIME_WAIT状态,等待2MSL(MSL:报文段最大生存时间),然后关闭连接。
        • 虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。
        • 所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
        • Client发送出最后的ACK回复,但该ACK可能丢失。 Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACKClient会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL
        • 所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)
        • MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。
        • 如果直到2MSLClient都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
  • 参考: TCP的三次握手与四次挥手理解及面试题

TCP的模型,状态转移

  • 四层TCP/IP模型如下:
    四层TCP/IP模型如下
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值