计算机网络面经之TCP协议

Posted 梅见西梅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算机网络面经之TCP协议相关的知识,希望对你有一定的参考价值。

1、为什么要三次握手

【 一句话,主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。 】

不能是两次:客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到(滞留)。此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接(正常传输)。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,服务器接着返回第一次请求的响应,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。

如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

不能是四次: 如果是四次握手,即第三次只是传输的响应报文段,第四次才传输数据。本来第三次握手就能传输数据了,这属于画蛇添足,也浪费了资源。 (可以但没必要)

2、为什么要四次挥手

【断开连接时,服务器端可能还在发数据,因此不能将响应的ACK和断开连接的请求一起发送】

​ 因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步挥手。

​ 服务端收到客户端的 FIN 标志,知道客户端想要断开这次连接了,但是,我服务端,我还想发数据呢?我等到发送完了所有的数据后,会发送一个 FIN 段来关闭此方向上的连接。接收方发送 ACK确认关闭连接。

3、为什么挥手要等待2MSL

【为了保证客户端发送的最后一个报文能成功到达服务器,客户端能够在2MSL中接收到这个服务端重传的报文(最后一次握手,客户端发送完最后一个报文后,如果2MSL内没有服务端没有收到,就会触发超时重传,在2MSL内就一定能收到这个重传请求)】

​ 为了保证客户端发送的最后一个ACK报文段能够到达服务器。这个ACK报文段可能丢失(客户端发的,第四次握手),因而使在Last-ACK状态的服务器收不到客户端已发送的FIN+ACK报文段的确认。服务器就会超时重传这个报文段,而客户端就能在2MSL时间内收到这个重传的FIN-ACK报文段。接着客户端重传一个确认,重新启动2MSL计时器。最后客户端和服务器端都能正常进入到CLOSED状态。

​ 如果服务器端在TIME-WAIT状态下不等待一段时间,而是在发送完ACK报文段就立即释放连接,那么客户端就无法收到服务器重传的FIN_ACK报文段,因而也就不会再发送一个报文段,这样服务器就无法进入CLOSED状态。

4、大量TIME_WAIT产生的原因和解决办法

产生原因:对于一些Web服务器,断开连接的是Server端,这样Server端就会进入TIME_WAIT状态,当在高并发的Web服务器中存在大量的连接,当断开时会产生大量的TIME_WAIT。

危害:在socket的TIME_WAIT结束之前,该socket会一直占用本地端口,在高并发和短连接的交互系统中,大量的TIME_WAIT会把可用的端口都占用且系统未能及时回收,就会 出现无法向服务端创建新的socket连接的情况 。

解决方法:将socket进行复用,允许TIME_WAIT的socket重新用于TCP的连接,将短链接设置为长链接

【一句话:高并发的服务器中有大量连接,而且主动断开连接的一方是服务器,因此在断开时会出现大量TIME_WAIT

5、TCP怎么保证可靠传输

可靠是指:不重复、不丢失、不失序

  • 确认和重传:接收方收到报文就会确认,发送方发送一段时间后没有收到确认就会重传。

  • 数据校验:TCP报文头有校验和,用于校验报文是否损坏。

  • 数据合理分片和排序:tcp会按最大传输单元(MTU)合理分片,接收方会缓存未按序到达的数据,重新排序后交给应用层。而UDP:IP数据报大于1500字节,大于MTU。这个时候发送方的IP层就需要分片,把数据报分成若干片,是的每一片都小于MTU。而接收方IP层则需要进行数据报的重组。由于UDP的特性,某一片数据丢失时,接收方便无法重组数据报,导致丢弃整个UDP数据报。

  • 流量控制:当接收方来不及处理发送方的数据,能通过滑动窗口,提示发送方降低发送的速率,防止包丢失。

  • 拥塞控制:当网络拥塞时,通过拥塞窗口,减少数据的发送,防止包丢失。

    【一句话:确认重传、合理分片、数据校验、流量控制、拥塞控制】

6、TCP流量控制

流量控制是为了控制发送方发送速率,保证接收方来得及接收。TCP 中采用滑动窗口来进行传输控制,滑动窗口的大小意味着接收方还有多大的缓冲区可以用于接收数据。发送方可以通过滑动窗口的大小来确定应该发送多少字节的数据。当滑动窗口为 0 时,发送方一般不能再发送数据报。

【一句话:控制发送方发送速率,保证接收方能接受】

7、TCP滑动窗口

窗口是缓存的一部分,用来暂时存放字节流。发送方和接收方各有一个窗口,接收方通过 TCP 报文段中的窗口字段告诉发送方自己的窗口大小,发送方根据这个值和其它信息设置自己的窗口大小。 (接收方控制发送方窗口)

发送窗口内的字节都允许被发送,接收窗口内的字节都允许被接收。 接收窗口只会对窗口内最后一个按序到达的字节进行确认,例如接收窗口已经收到的字节为{31, 34, 35},其中{31}按序到达,而 {34, 35} 就不是,因此只对字节 31 进行确认。发送方得到一个字节的确认之后,就知道这个字节之前的所有字节都已经被接收。

8、TCP拥塞控制

如果网络出现拥塞,分组将会丢失,此时发送方会继续重传,从而导致网络拥塞程度更高。因此当出现拥塞时,应当控制发送方的速率。这一点和流量控制很像,但是出发点不同。流量控制是为了让接收方能来得及接收,而拥塞控制是为了降低整个网络的拥塞程度。 TCP 主要通过四个算法来进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。

发送方需要维护一个叫做拥塞窗口(cwnd)的状态变量,注意拥塞窗口与发送方窗口的区别:拥塞窗口只是一个状态变量,实际决定发送方能发送多少数据的是发送方窗口。

【流量控制:控制接收方;拥塞控制:控制整个网络】

(1)慢开始与拥塞避免

慢开始:发送的最初执行慢开始,令 cwnd = 1,发送方只能发送 1 个报文段;当收到确认后,将 cwnd 加倍,因此之后发送方能够发送的报文段数量为:2、4、8 …(拥塞窗口每次都2倍增长)注意到慢开始每个轮次都将 cwnd 加倍,这样会让 cwnd 增长速度非常快,从而使得发送方发送的速度增长速度过快,网络拥塞的可能性也就更高。

拥塞避免:设置一个慢开始门限 ssthresh,当 cwnd >= ssthresh 时,进入拥塞避免,每个轮次只将 cwnd 加 1。如果出现了超时,则令 ssthresh = cwnd / 2,然后重新执行慢开始。

(2)快重传与快恢复

快重传: 就是使发送方尽快进行重传,而不是等超时重传计时器超时再重传。在发送方,如果收到三个重复确认,那么可以知道下一个报文段丢失,此时执行快重传,立即重传下一个报文段。例如收到三个 M2,则 M3 丢失,立即重传 M3。

快恢复: 在这种情况下,只是丢失个别报文段,而不是网络拥塞。因此执行快恢复,令 ssthresh = cwnd / 2 ,cwnd = ssthresh,注意到此时直接进入拥塞避免。

注意:(1)慢开始和快恢复的快慢指的是 cwnd 的设定值,而不是 cwnd 的增长速率。慢开始 cwnd 设定为 1,而快恢复 cwnd 设定为 ssthresh。 (2)快重传指的是发送方的动作(重传报文),而不是对拥塞窗口的改变;而快恢复指的是对拥塞窗口的变化。

以上是关于计算机网络面经之TCP协议的主要内容,如果未能解决你的问题,请参考以下文章

社招面经之个人总结

社招面经之个人总结

社招面经之个人总结

面经之java缓存总结,从单机缓存到分布式缓存架构

02 网络面经:一个TCP连接可以发送多少个HTTP请求?

02 网络面经:一个TCP连接可以发送多少个HTTP请求?