计算机网络学习笔记(五)---TCP协议

TCP 在IP不可靠的服务之上创建了可靠数据传输服务。TCP 的可靠数据传输服务确保一个进程从其接收缓存中读出的数据流是无损坏、无间隔、非冗余和按序的数据流;即该字节流与连接的另一端发出的字节流完全相同 。

TCP 被称为是面向连接的,在一个应用进程开始向另一个应用进程发送数据之前,这两个进程必须先相互“握手”,即它们必须相互发送某些预备报文段,以建立确保数据传输的参数。 作为 TCP 连接建立的一部分,连接的双方都将初始化与 TCP 连接相关的 TCP 状态变量。

TCP 连接提供全双工服务:如果一台主机上的进程 A 与另一台主机上的进程 B 存在一条 TCP 连接,那么应用层数据就可在从进程 B 流向进程 A 的同时,也从进程 A 流向进程 B 。 TCP 连接也是点对点的,即在单个发送方与单个接收方之间的连接。 “多播”即在一次发送操作中,从一个发送方将数据传送给多个接收方,对 TCP 来说是不可能的 。

TCP通过三次握手建立连接。一旦建立起一条 TCP 连接,两个应用进程之间就可以相互发送数据了。客户进程通过套接字传递数据流。 TCP 将这些数据引导到该连接的发送缓存里,发送缓存是在三次握手时设置的缓存之一 。 接下来 TCP 就会不时从发送缓存里取出一块数据。TCP可从缓存中取出并放入报文段中的数据数量受限于最大报文段长度( Maximum Segmenl Size, MSS ) 。 MSS 通常根据最初确定的由本地发送主机发送的最大链路层帧长度(即所谓的最大传输单元( Maximum Transmission Unit, MTU)来设置 。

建立一个 TCP 连接需要客户端与服务器端同步三个信息:

  • Socket:由 IP 地址和端口号组成
  • 序列号:用来解决乱序问题等
  • 窗口大小:用来做流量控制

TCP 四元组可以唯一的确定一个连接,四元组包括如下:

  • 源地址,源端口,目的地址,目的端口
  • 源地址和目的地址的字段(32位)在 IP 头部中,作用是通过 IP 协议发送报文给对方主机。源端口和目的端口的字段(16位)在 TCP 头部中,作用是告诉 TCP 协议应该把报文发给哪个进程。

一、TCP报文段结构

头部长度字段给出了头部的长度,以32位字为单位。作为一个4位的字段, TCP被限制为只能带60字节的头部。而不带选项大小是20字节。16 比特的接收窗口字段用于流量控制,该字段用于指示接收方愿意接受的字节数量。8位字段:
1. CWR---拥塞窗口减小(发送方降低它的发送速率);
2. ECE---其值为 1 则通知对方,从对方到这边的网络有阻塞。在收到数据包的 IP 首部中 ECN 为 1 时将 TCP 首部中的 ECE 设为 1
3. URG---该位设为 1,表示包中有需要紧急处理的数据
4. ACK---该位为 1 时,「确认应答」的字段变为有效,TCP 规定除了最初建⽴连接时的SYN 包之外该位必须设置为 1  ;
5. PSH---该位设为1表示需要将收到的数据立刻传给上层应用协议,若设为 0则先将数据进行缓存
6. RST---该位设为 1,表示 TCP 连接出现异常必须强制断开连接
7. SYN---用于初始化一个连接的同步序列号;
8. FIN---该报文段的发送方已经结束向对方发送数据。

二、三次握手与四次挥手

三次握手

 第一步:客户端的 TCP 首先向服务器端的 TCP 发送一个特殊的 TCP 报文段 。 该报文段中不包含应用层数据 。 在报文段的首部中的一个标志位(SYN 比特)被置为1。这个特殊报文段被称为 SYN 报文段。客户会随机地选择一个初始序号(client_isn ),并将此编号放置于该起始的 TCP SYN报文段的序号字段中 。 该报文段会被封装在一个 IP 数据报中发送给服务器 。

第二步:包含 TCP SYN 报文段的 IP 数据报到达服务器主机,服务器会从该数据报中提取出 TCP SYN 报文段,为该 TCP 连接分配 TCP 缓存和变量,并向该客户 TCP 发送允许连接的报文段。 (在完成三次握手的第三步之前分配这些缓存和变量,使得 TCP 易于受到称为 SYN 洪泛的拒绝服务攻击。 )这个允许连接的报文段也不包含应用层数据 。 但是,在报文段的首部却包含 3 个重要的信息 。 首先, SYN 比特被置为1。其次,该 TCP 报文段首部的确认号字段被置为 client_isn + 1 。 最后,服务器选择自己的初始序号( server_isn ),并将其放置到 TCP 报文段首部的序号字段中 。 该允许连接的报文段有时被称为 SYNACK 报文段( SYN + ACK segment ) 。

第三步:在收到 SYNACK 报文段后,客户端也要给该连接分配缓存和变量,同时向服务器发送另外一个报文段:这最后一个报文段对服务器的允许连接的报文段进行了确认(该客户通过将值 server_isn + 1 放置到 TCP 报文段首部的确认字段中来完成此项工作)。因为连接已经建立了,所以该 SYN比特被置为 0 。此阶段可以在报文段负载中携带客户到服务器的数据。

一旦完成这 3 个步骤,客户和服务器主机就可以相互发送包括数据的报文段了 。 在以后每一个报文段中, SYN 比特都将被置为 0。 为了创建该连接,在两台主机之间发送了 3 个分组。 由于这个原因 , 这种连接创建过程通常被称为 3 次握手。

四次挥手

客户端应用进程发出一个关闭连接命令。 这会引起客户 TCP 向服务器进程发送一个特殊的TCP 报文段 。 这个特殊的报文段让其首部中的 FIN 比特被设置为 1 。 当服务器接收到该报文段后,就向发送方回复一个确认报文段。 然后服务器发送它自己的终止报文段,其 FIN 比特被置为1。最后客户端对服务器的终止报文段进行确认,等待2MSL( Maximum Segment Life)后,用于该连接的所有资源都被释放了。

MSL 是 Maximum Segment Lifetime,报文最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。TIME_WAIT至少需要持续2MSL时长,第一个MSL是为了等自己发出去的最后一个ACK从网络中消失,第二个是为了等在对端收到ACK之前可能重传的FIN报文从网络中消失。

状态转移图

特殊情况

当一台主机接收到一个 TCP 报文段,其端口号或源 IP 地址与该主机上进行中的套接字都不匹配时,例如一台主机接收了具有目的端口 80的一个 TCP SYN 分组,但该主机在端口 80 不接受连接(即它不在端口 80 上运行 Web 服务器)。则该主机将向源发送一个特殊重置报文段,该 TCP 报文段将 RST 标志位置为 1 。 当主机发送一个重置报文段时,它告诉该源“我没有那个报文段的套接字,不要再发送该报文段了” 。 当一台主机接收一个 UDP 分组,它的目的端口与进行中的 UDP 套接字不匹配,该主机发送一个特殊的 ICMP 数据报。

三、超时与重传

TCP 采用累积确认,发送方收到ACK的值 y 确认了字节编号在 y 前的所有字节都已经收到。TCP 重传具有最小序号的还未被确认的报文段。每次 TCP 重传时都会将下一次的超时间隔设为先前值的两倍。

超时触发重传存在的问题之一是超时周期可能相对较长 。 当一个报文段丢失时,这种长超时周期迫使发送方延迟重传丢失的分组,因而增加了端到端时延。发送方通常可在超时事件发生之前通过注意冗余 ACK 来较好地检测到丢包情况 。如果 TCP 发送方接收到对相同数据的 3 个冗余 ACK ,说明跟在这个已被确认过 3 次的报文段之后的报文段已经丢失 , TCP 就执行快速重传( fast retransmit ) ,即在该报文段的定时器过期之前重传丢失的报文段 。

TCP 确认是累积的,正确接收但失序的报文段不会被接收方逐个确认 。TCP 发送方仅需维持已发送过但未被确认的字节的最小序号( SendBase)和下一个要发送的字节的序号。选择确认:允许 TCP 接收方有选择地确认失序报文段,而不是累积地确认最后一个正确接收的有序报文段 。 当将该机制与选择重传机制结合起来使用时(即跳过重传那些已被接收方选择性地确认过的报文段) , TCP 看起来就像通常的 SR 协议 。 

四、流量控制

TCP 提供流量控制服务以消除发送方使接收方缓存溢出的可能。流量控制因此是一个速度匹配服务,即发送方的发送速率与接收方应用程序的读取速率相匹配。

TCP 通过让发送方维护一个接收窗口来提供流量控制 。接收窗口用于给发送方一个指示---接收方还有多少可用的缓存空间。因为TCP 是全双工通信,在连接两端的发送方都各自维护一个接收窗口。TCP 不允许已分配的缓存溢出,因此接收缓存不能小于 从网络中到达的并且已放入主机接收缓存的数据流的最后一个字节的编号 与应用进程从缓存读出的数据流的最后一个字节的编号的差。

TCP连接的每一端都可收发数据。连接的收发数据量是通过一组窗口结构来维护的。每个TCP活动连接的两端都维护一个发送窗口结构和接收窗口结构。每个TCP头部的窗口大小字段表明接收端可用缓存空间的大小,以字节为单位。
每个TCP报文段都包含ACK号和窗口通告信息, TCP发送端可以据此调节窗口结构。窗口左边界不能左移,因为它控制的是已确认的ACK号,具有累积性,不能返回。当得到的ACK号增大而窗口大小保持不变时(通常如此),就说窗口向前“滑动”。若随着ACK号增大窗口却减小,则左右边界距离减小。当左右边界相等时,称之为零窗口。此时发送端不能再发送新数据。这种情况下, TCP发送端开始探测对方窗口,伺机增大窗口。
与发送端窗口一样,接收端窗口结构也包含一个左边界和右边界,但窗口内的字节并没有区分。对接收端来说,到达序列号小于左窗口边界被认为是重复数据而丢弃,超过右边界的则超出处理范围,也被丢弃。由于TCP的累积ACK结构,只有当到达数据序列号等于左边界时,数据才不会被丢弃,窗口才能向前滑动。对选择确认TCP来说,使用SACK选项,窗口内的其他报文段也可以被接收确认,但只有在接收到等于左边界的序列号数据时,窗口才能前移。
与TCP相反,UDP 并不提供流量控制 。

五、拥塞控制

路由器因无法处理高速率到达的流量而被迫丢弃数据信息的现象称为拥塞。拥塞控制用于防止网络因为大规模的通信负载而瘫痪。其基本方法是当有理由认为网络即将进人拥塞状态(或者已经由于拥塞而出现路由器丢包情况)时减缓TCP传输。拥塞控制的难点在于准确地判断何时需要减缓且如何减缓TCP传输,以及何时恢复其原有的速度。
下面讨论TCP的两个核心算法:慢启动和拥塞避免。在任一时刻, TCP只运行一个算法,但两者可以相互切换。

慢启动

拥塞窗⼝ cwnd是发送⽅维护的⼀个的状态变量,它会根据⽹络的拥塞程度动态变化。 当一个新的TCP连接建立或检测到由重传超时(RTO)导致的丢包时,需要执行慢启动。 TCP发送端长时间处于空闲状态也可能调用慢启动算法。慢启动的目的是使TCP在用拥塞避免探寻更多可用带宽之前得到cwnd值,以及帮助TCP建立ACK时钟。通常,TCP在建立新连接时执行慢启动,直至有丢包时,执行拥塞避免算法进入稳定状态。
TCP以发送一定数目的数据段开始慢启动(在SYN交换之后),称为初始窗口(Initial Window, IW)。 IW的值初始设为一个SMSS (发送方的最大段大小)。大部分情况下, SMSS为接收方的MSS (最大段大小)和路径MTU (最大传输单元)两者中较小值。在接收到一个数据段的ACK后,通常cwnd值会增加到2,接着会发送两个数据段。如果成功收到相应的新的ACK, CWnd会由2变4,由4变8,以此类推。假设某个TCP连接中接收方的通知窗口非常大,这时cwnd就是影响发送速率的主要因素(设发送方有较大发送需求)。如前所述, cwnd会随着RTT呈指数增长。因此,最终cwnd会增至很大,大量数据包的发送将导致网络瘫痪。当发生上述情况时, cwnd将大幅度减小(减至原值一半)。这是TCP由慢启动阶段至拥塞避免阶段的转折点,与cwnd和慢启动阈值(sIow start threshold,ssthresh)相关。

如果发生由超时指示的丢包事件(即拥塞) , TCP 发送方将 ssthresh (慢启动阈值)设置为拥塞窗口值的一半,然后将 cwnd 设置为1并重新开始慢启动过程。因为当检测到拥塞时 ssthresh 设为 cwnd 的一半,当到达或超过ssthresh 的值时,结束慢启动并且 TCP 转移到拥塞避免模式。进入拥塞避免模式时,TCP 更为谨慎地增加 cwnd 。如果检测到 3 个冗余 ACK,这时 TCP 执行快速重传并进入快速恢复状态 。 

拥塞避免

一旦进入拥塞避免状态, cwnd 的值大约是上次遇到拥塞时的值的一半, TCP 无法每过一个 RTT 再将 cwnd 的值翻番,而是采用了一种较为保守的方法,每个 RTT 只将 cwnd 的值增加一个 MSS 。通用的方法是对于 TCP 发送方无论何时收到一个新的确认,就将 cwnd 增加 1/cwnd。

如果 MSS 是 1460 字节并且 cwnd 是 14 600 字节,则在一个 RTT 内发送 10 个报文段 。 每个到达 ACK (假定每个报文段一个 ACK)增加 1/ 10 MSS的拥塞窗口长度,因此在收到对所有 10 个报文段的确认后,拥塞窗口的值将增加了一个 MSS 。

随着每个新的ACK到达, cwnd会有相应的小幅增长,整体增长率呈现轻微的次线性。通常认为拥塞避免阶段的窗口随时间线性增长,而慢启动阶段呈指数增长。这个函数也称为累加增长,因为每成功接收到相应数据, cwnd就会增加一个特定值。

当出现超时时, TCP 的拥塞避免算法行为相同 。 与慢启动的情况一样, ssthresh 的值被更新为 cwnd 值的一半,cwnd 的值被设置为 1 个 MSS。

三个冗余 ACK 事件:在这种情况下,网络继续从发送方向接收方交付报文段(就像由收到冗余 ACK 所指示的那样)。 TCP 对这种丢包事件的行为,相比于超时指示的丢包,应当不那么剧烈 。TCP 将 ssthresh 的值记录为 cwnd 的值的一半,将 cwnd 的值减半,接下来快速重传并进入快速恢复状态。

快速恢复

在快速恢复中,对于引起 TCP 进入快速恢复状态的缺失报文段,对收到的每个冗余的ACK, cwnd 的值增加一个 MSS。当丢失报文段的一个 ACK 到达时, TCP 在降低cwnd后进入拥塞避免状态 。 如果出现超时事件,快速恢复在执行如同在慢启动和拥塞避免中相同的动作后,迁移到慢启动状态:当丢包事件出现时, cwnd 的值被设置为 1 个MSS ,并且 ssthresh 的值设置为 cwnd 值的一半 。 快速恢复是 TCP 推荐的而非必需的。

六、TCP连接状态

  • CLOSED:初始状态。

  • LISTEN:服务器处于监听状态。

  • SYN_SEND:客户端socket执行CONNECT连接,发送SYN包,进入此状态。

  • SYN_RECV:服务端收到SYN包并发送服务端SYN包,进入此状态。

  • ESTABLISH:表示连接建立。客户端发送了最后一个ACK包后进入此状态,服务端接收到ACK包后进入此状态。

  • FIN_WAIT_1:终止连接的一方(通常是客户机)发送了FIN报文后进入。等待对方FIN。

  • CLOSE_WAIT:(假设服务器)接收到客户机FIN包之后等待关闭的阶段。在接收到对方的FIN包之后,自然是需要立即回复ACK包的,表示已经知道断开请求。但是本方是否立即断开连接(发送FIN包)取决于是否还有数据需要发送给客户端,若有,则在发送FIN包之前均为此状态。

  • FIN_WAIT_2:此时是半连接状态,即有一方要求关闭连接,等待另一方关闭。客户端接收到服务器的ACK包,但并没有立即接收到服务端的FIN包,进入FIN_WAIT_2状态。

  • LAST_ACK:服务端发动最后的FIN包,等待最后的客户端ACK响应,进入此状态。

  • TIME_WAIT:客户端收到服务端的FIN包,并立即发出ACK包做最后的确认,在此之后的2MSL时间称为TIME_WAIT状态。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值