您的位置:首页 > 理论基础 > 计算机网络

计算机网络中的TCP/UDP协议到底是怎么回事(二)

2016-03-25 11:53 351 查看
上一篇博客阐述了TCP/IP五层网络结构模型以及一些关于TCP、UDP的基础知识,这篇博客会接着写一些关于TCP拥塞控制的算法以及对TCP中常有的疑问进行解答。

TCP拥塞控制

首先了解几个概念,为下面的叙述做铺垫

拥塞窗口(cwnd):TCP拥塞控制中的主要参数,表示发送端下一次最多可以发送的数据分包的个数,是来自发送端的流量控制。

接收端窗口(rwnd):又称通知窗口(
Advertise Window
),接受端目前每次所能接收的数据分组的最大个数,是来自接收端的流量控制。

慢开始门限(ssthresh):当拥塞窗口增长到慢开始门限时,启动拥塞避免算法(后面会具体阐述)。

拥塞控制常用算法:慢开始、拥塞避免、快重传、快恢复。

最初,发送方不知道接收方的容纳能力,如果初次就发送较大量的数据,极有可能造成整个网络的瘫痪,TCP为了防止此类问题的出现,在通信一开始就会通过一个叫慢开始的算法得到的数值,对发送数据量进行控制。

慢开始:

由于需要考虑拥塞控制和流量控制两个方面的内容,发送端的发送窗口为
min(cwnd,rwnd)
,但是
rwnd
是由对端确定的,网络环境对其没有影响,所以在考虑拥塞的时候我们一般不考虑
rwnd
的值,我们暂时只讨论如何确定
cwnd
值的大小。

在执行慢开始算法时,拥塞窗口
cwnd
的初始值为 1,发送第一个报文段。当发送端收到来自接收端的
ACK
之后,拥塞窗口开始以1、2、4这样的指数形式增长。当拥塞窗口
cwnd
增长到慢开始门限值
ssthresh
时,就改为执行拥塞避免算法,拥塞窗口按线性规律增长。

拥塞避免:

最初,拥塞窗口指数增长,可以很快进行大数据的发送,最大限度的利用网络宽带资源。当达到慢开始门限值,开始进入拥塞避免阶段,拥塞窗口开始加法增加。这样就可以避免增长过快导致网络拥塞,慢慢的增加调整到网络的最佳值。

快重传与快速恢复

上面都没有遇到网络拥塞,当真正遇到网络拥塞时,如何处理呢?当发送方连续收到三个重复的ACK之后,TCP会进入快速重传、快速恢复的阶段。

为什么叫快速重传呢?如果当发送端接收到三个重复的确认ACK时,则断定分组丢失,立即重传丢失的报文段,而不必等待重传计时器超时,相比之下,前者速度更快。

快速恢复的主要步骤:

当收到3个重复ACK时,把
ssthresh
设置为
cwnd
的一半,把
cwnd
设置为
ssthresh
的值加3,然后重传丢失的报文段。

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

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



TCP窗口变化

当TCP通信开始之后,网络吞吐量会逐渐上升,但是随着网络拥堵的发生,吞吐量也会急速下降。于是会再次进入吞吐量慢慢上升的过程。但是所谓TCP的吞吐量的特点就好像是在逐渐占领网络宽带的感觉。

TCP疑问解答

为什么采用三次握手而不是二次握手?

client
发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达
server
。本来这是一个早已失效的报文段。但
server
收到此失效的连接请求报文段后,就误认为是
client
再次发出的一个新的连接请求。于是就向
client
发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要
server
发出确认,新的连接就建立了。由于现在
client
并没有发出建立连接的请求,因此不会理睬
server
的确认,也不会向
server
发送数据。但
server
却以为新的运输连接已经建立,并一直等待
client
发来数据。这样,
server
的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,
client
不会向
server
的确认发出确认。
server
由于收不到确认,就知道
client
并没有要求建立连接。”

TCP三次握手时,第三次握手失败怎么办?

如果三次都成功的话:

客户端发出了SYN包给服务器,客户端进入SYN_SEND状态。

服务器收到SYN包后发出SYN+ACK数据包,服务器进入SYN_RECV状态。

客户端收到SYN+ACK后发出ACK给服务器,客户端进入ESTABLISH状态

服务器收到最后的ACK,服务器进入ESTABLISH状态。

我们了解一下TCP状态转换图和状态伪码可以发现:

case:SYN_RECV状态
if(收到ACK报文)
进入ESTABLISH状态
if(超时)
发送RTS报文,进入CLOSED状态
if(收到“关闭报文”)
发送FIN报文,进入FIN_WAIT_1状态
if(收到RTS报文)
进入LISTEN状态
if(收到其他报文段或报文)
发出差错报文
break

当第三次握手失败时的处理操作,可以看出当失败时服务器并不会重传ACK报文,而是直接发送RTS报文段,进入CLOSED状态。这样做的目的是为了防止SYN洪泛攻击。

何为SYN洪泛攻击呢?在TCP连接建立过程中很容易碰到严重的的安全问题,称为SYN洪泛攻击。当一个或多个恶意攻击者向服务器发送大量的SYN报文时,服务器认为不同客户发来了打开请求,于是就回分配资源。然后,服务器向假冒的客户发送SYN+ACK报文,而这些报文都丢失了。如果在第三次握手这段很短的时间内,服务器大量资源被占用而没有被利用,服务器会因为资源耗尽而无法接受合法客户的连接请求。这种SYN洪泛攻击称为拒绝服务攻击的安全攻击,即攻击者用大量的请求垄断一个系统,使这个系统因超载而拒绝为合法的请求提供服务。(更多内容请参考TCP/IP协议簇一书)

关闭连接时半关闭选项的四向握手

TCP连接是全双工的,所以它允许两个方向的数据传输被独立关闭。换言之,通信的一端可以发送结束报文段给对方,告诉它本端已经完成了数据的发送,但允许继续接收来自对方的数据,直到对方也发送结束报文段以关闭连接。TCP连接的这种状态称为半关闭(
half close
)状态。

当客户端向服务器发送一个FIN报文段后,此连接被半关闭了。服务器发送ACK报文段来接受这个半关闭。但是服务器仍然可以发送数据,当服务器把处理完的数据都发送完毕之后,发送FIN报文段(半关闭),并且被客户发来的ACK予以确认(关闭)。

当关闭连接时最后一个ACK丢失怎么办?

如果最后一个ACK丢失的话,TCP就会认为它的FIN丢失,进行重发FIN。在客户端收到FIN后,就会设置一个2MSL计时器,2MSL计时器可以使客户等待足够长的时间,使得在ACK丢失的情况下,可以等到下一个FIN的到来。如果在TIME-WAIT状态汇总有一个新的FIN到达了,客户就会发送一个新的ACK,并重新设置2MSL计时器。

示例图解如下:



半关闭终止时间图

如果重传FIN到达客户端时,客户端已经进入CLOSED状态时,那么客户就永远收不到这个重传的FIN报文段,服务器收不到ACK,服务器无法关闭连接。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: