【计算机网络】传输层 - TCP协议

特点

  • 面向连接, 使用TCP传输数据前必须建立连接,完毕后须释放连接。
  • 点对点, 每个TCP连接只能有两个端点。
  • 可靠传输, 通过TCP的超时重传和捎带确认机制保证传输的数据能够按序正确到达。
  • 流量控制和拥塞控制,在网络情况较差时可控制传输速率。
  • 双工通信, TCP连接的两端都设有发送缓存和接收缓存, 会在合适的时机处理数据。
  • 面向字节流, TCP流指流入到进程或从进程流出的字节序列,TCP吧应用程序交下来的数据堪称是一串连续的字节流处理。

socket套接字

TCP把连接作为最基本的抽象,因此每一条连接都需要有两个端点,而套接字(socket)就是TCP连接的端点。

格式
套接字 socket = (IP地址 : 端口号)

每一条TCP连接唯一地被两个套接字确定。

同一个IP地址可以有不同的TCP连接, 同一个端口号也可有不同的TCP连接。

注:
socket也指操作系统提供的一套应用编程接口 API。
由于TCP/IP的核心内容被封装在操作系统中,如果应用程序要使用TCP/IP,则需要使用操作系统提供的socket API来实现。

TCP报文

在这里插入图片描述

  • 源端口和目的端口 各2字节

用来写入源端口号和目的端口号。

  • 序号 4字节

4字节共2^ 32个序号。序号增加到 2^32 - 1 (32个1)后又回到0。
用来为字节流中的每一个字节都按序编号,序号在连接建立时设置。
首部中的序号表示该数据报中发送的第一个字节的序号。

  • 确认号 4字节

表示期望收到对方下一个报文段的数据的第一个字节的序号。例如A向B发送了序号为300,长度为100的数据报,B期望继续接受数据,则需要将发送给A的确认报文中把确认号设置为401。

  • 数据偏移 4位

指出TCP报文段首部的长度。 因为首部中还有长度不确定的选项字段, 因此需要额外用数据偏移字段记录首部的长度。

数据偏移字段单位为32bit(4字节)。 4位能表示最大二进制数为15, 因此该字段最大能表示60字节,这也是TCP首部的最大长度。

  • 保留 6位

6个控制位

  • 紧急URG 1位

URG = 1 时表示紧急指针字段有效。它告诉系统次报文中有紧急数据,应当尽快传送,而不按原来的排队顺序传送。

  • 确认ACK 1位

当ADC = 1时确认号字段才有效, 在TCP连接建立后所有传送的报文都必须把ACK设为1.

  • 推送PSH1位

PSH = 1表示推送操作, 立即创建一个表文段发送出去, 接收方TCP收到PSH = 1的报文段时就尽快的交付给接收应用进程。

  • 复位RST1位

当RST = 1 时,表明TCP连接中出现严重差错,必须释放连接,然后重新建立连接。 它还用来拒绝非法的报文段或拒绝打开一个连接。

  • 同步SYN1位

在建立连接时用来同步序号。
当SYN = 1 且 ACK = 0时 表明这是一个连接请求报文段。 对方若同意连接, 则应在响应的报文段中使SYN = 1 和 ACK = 1,。

  • 终止FIN1位

FIN = 1是表示发送方的数据发送完毕, 将要释放连接。

窗口 2字节

最大 2^16 - 1, 接受方的缓存大小有限, 所以需要使用该字段表示发送方的接收窗口大小。

窗口值经常在动态变化着.

  • 校验和2字节

校验范围包括首部和数据这两部分. 和UDP一样需要加伪首部.

  • 紧急指针 2字节

指出本报文段中的紧急数据的字节数.

  • 选项
    长度可变, 最长可达40字节, 没有选项时首部长20字节,

TCP连接建立

三次握手

在这里插入图片描述

A为客户端, B为服务器, 最初二者都为CLOSE关闭状态。

B服务器进程先创建TCB(Transmission Control Block)传输控制块, 进入Listen状态准备接受客户进程的连接请求。

  1. 客户端A创建TCB, 然后向客户端发送请求报文, 其中SYN = 1, 表示建立连接信号有效, ACK = 0 , 因为是第一次请求还没有确认号所以确认信号无效,seq = x 设置一个初始序号。 TCP规定SYN = 1 的报文不能携带数据, 但要消耗一个序列号。 发送完成后A客户端进入SYN-SENT状态。
  2. 服务器B收到A的连接请求后,如同意连接则需要向A发送确认,使 SYN = 1,表示连接请求, ACK = 1 , 因为已经收到了A的seq序号, 将要请求下一个序号,所以ACK生效, 并且确认号ack = x + 1。
    同时B还要带上自己设置的初始序号seq = y。 发送完成后B服务端进入SYN-RCVD。
  3. 客户端A收到服务端B的确认后, 需要再向服务端B发送一个确认。 设置seq = x + 1,ACK = 1, 确认号ack = y + 1(SYN = 0),向B进行确认。 发送后A进入ESTABLISHED状态。服务端B收到后也进入ESTABLISHED状态。

抓包

在这里插入图片描述

第一次握手
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

为什么要三次握手

需要建立可靠的连接, 则双方都需要确认双方的接收请求和发送请求功能都正常。

  • 第一次握手,服务端B收到A的请求, 则B可以确认A的发送功能和B的接收功能都正常。
  • 第二次握手,客户端A收到B的确认, 则A可以确认A和B的发送和接收功能都正常。
  • 第三次握手, 服务端B收到A的确认,则B可以确认A的接收功能和B的发送功能都正常。

因此, 三次握手才能够建立可靠的连接。

只有两次握手带来的问题

  • 网络中客户端发送的滞留失效报文在延时的情况下到达服务端时, 服务器返回一次确认后便认为连接已经建立, 而此时客户端在CLOSE状态并没有发起连接, 则此时服务端进入无效的等待, 浪费资源.
  • 当服务器回答客户端发送的滞留失效的延时报文时, 如果客户端又恰好发起连接进入SYN-SENT状态, 客户端则会收到延时报文的确认, 从而会导致双方得到了错误的的序号和确认号, 导致大量的数据包会被丢弃,造成系统资源的浪费。

TCP连接释放

四次挥手

在这里插入图片描述

首先A和B都处于ESTABLISHED连接状态

  1. A的应用进程先向其TCP发出连接释放报文, 设置 FIN = 1 , seq = u, u为前面传送过的最后一个字节的序号加1, 并停止发送数据, 主动关闭连接, 进入FIN-WAIT-1状态。
  2. B服务端收到连接释放报文后发出确认, 确认序号ack = u + 1, seq = v 等于B之前传送的报文的最后一个字节加1, 然后B进入CLOSE-WAIT状态。此时连接处于半关闭状态,A已经没有数据要发送了, 但B若发送输出A仍要接收。 这个状态可能持续一段时间。A在收到B的确认后进入FIN-WAIT-2状态,等待B的释放连接报文。
  3. 若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接。这时B发出连接释放报文,设置FIN = 1 ,seq = w (表示半关闭状态发送的最后一个字节序号加1), 重复上次的确认号ack = u + 1, 之后B进入LAST-ACK状态, 等待A的确认。
  4. A在收到B的连接释放报文段后,需对B进行回复确认,在确认报文段中设置 ACK = 1, ack = w + 1, seq = u + 1(FIN = 1 消耗序列号), 之后进入TIME-WAIT状态。 此时TCP连接还没有被释放掉, 必须经过2MSL后A才能进入CLOSE状态。 MSL(Maxinmum Segment Lifetime)最长报文段寿命,RFC 793建议设置为2分钟,可根据具体情况对时长进行设置。所以进入TIME-WAIT后客户端还要经过4分钟才能进入CLOSE状态。 服务端接接收到客户端的确认报文后也进入CLOSE状态。

抓包

在这里插入图片描述

TIME-WAIT

为什么客户端A必须在TIME-WAIT状态等待2MSL呢?

  • 第四次挥手, A发送最后一个ACK报文段有可能丢失, 处在LAST-ACK状态的B收不到最后一个确认报文,导致B不能正常关闭连接进入CLOSE状态。 而如果A等待2MSL,则B在收不到确认报文时会超时重传第三次挥手的FIN + ACK报文, A在2MSL内可以继续接受B发送的该报文,并重传一次确认,重新启动2MSL计时器。这样就能够保证B也能正常释放TCP连接。
  • 2MSL可以使本连接持续时间内所产生的所有报文段都在网络中消失。这样可以使下一个新的连接不会出现旧的连接报文段。

保活计时器

如果客户端与服务器建立了TCP连接后,客户端突然发生了故障。使用保活计时器可以防止服务器继续无效等待下去。

服务器每收到一次客户的数据,就重新设置保活计时器,通常是两小时。两小时没有收到客户的数据,则服务器每隔75分钟发送一个探测报文段。若连续发送10个仍无客户响应,服务器就认为客户端出了故障,并关闭该链接。

TCP可靠传输

TCP通过超时重传实现可靠传输。

当一个已经发送的报文在一定时间内未收到确认,则重传该报文, 该时间成为超时时间。

一个报文从发发送到收到确认所需的时间称为往返时间 RTT, 对RTT进行加权平均的往返时间成为RTTs(平滑往返时间)。
在这里插入图片描述
其中,0 ≤ a < 1,RTTs 随着 a 的增加更容易受到 RTT 的影响。

超时时间应该略大于RTTs值,TCP使用的超时时间:
123
其中 RTTd 为偏差的加权平均值。

TCP滑动窗口

在这里插入图片描述

发送缓存用来存放:

  • 应用程序准传送给TCP准备发送的数据
  • TCP已经发送但尚未收到确认的数据

接收缓存用来存放:

  • 按序到达的、但尚未被应用程序读取的数据
  • 未按序到达的数据

滑动窗口是缓存的一部分, 用来暂时存放字节流。接收方通过TCP报文中的窗口字段告诉发送方自己的窗口大小,接收方通过该字段设置自己的发送窗口大小。

发送窗口里的数据:

  • 已经发送但未确认的数据
  • 允许发送但还未来得及发送的数据

接收窗口里的数据:

  • 未按序到达的数据
  • 可以被可以接收的数据

TCP为全双工通信,通信的双方都有自己的发送窗口和接收窗口,也在同时发送和接收数据。

TCP流量控制

在这里插入图片描述

如图, 如果发送方数据发送过快, 接收方的应用程序接收按序到达的数据太慢,就会导致接收缓存渐渐被填满,造成数据的丢失。

利用滑动窗口机制可以方便地在TCP连接上实现对发送方的流量控制。

接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。

如果设置发送方的窗口为0, 则发送方会启动一个计时器, 定时发送探测报文, 从而防止产生僵局。

TCP拥塞控制

在计算机网络中的带宽, 交换节点的缓存和处理机等都是网络的资源, 如果在某一时间对这些资源的需求超过了可提供的部分, 就会产生拥塞, 网络性能就会变差, 。

因此当出现拥塞时, 发送方应当控制其传送速率。

在这里插入图片描述

TCP 主要通过四个算法来进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。

在这里插入图片描述

慢开始与拥塞避免

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

慢开始:令cwnd = 1, 发送方只能发送一个报文段, 在收到确认后,cwnd翻倍, cwnd = 2, 依次进行,cwnd的数量依次翻倍,2,4,8,16 …

拥塞避免: cwnd因为成指数倍增长,增长速率非常快, 为了避免增长过快导致的网络拥塞, 需要设置一个慢开始门限 ssthresh, 当cwnd >= ssthresh时, 进入拥塞避免, 每个轮次只讲cwnd增1。

如果出现了超时,则ssthresh 设置为超时时的 cwnd / 2 , 再重新执行慢开始。

快重传与快恢复

在这里插入图片描述

快重传: 快重传不需要接收方等待自己发送数据时稍待确认, 而是在接收数据后立即发送确认。 即使收到了失序的报文段也要立即发送正确的确认。

如图, 接收方收到了M1, M2 的报文段后, M3报文段丢失,之后又收到了三个报文段M4,M5和M6, 并发送了三个M2的确认, 接收方收到三个队M2的重复确认后立即重传M3。

这种情况下, 只是出现意外丢失个别的报文段,而不是网络拥塞, 因此执行快恢复,零ssthresh = cwnd / 2, cwnd = ssthresh, 并直接进入拥塞避免。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值