TCP协议详解

TCP 协议详解

TCP 服务的特点

面向连接、字节流、可靠传输。
TCP连接是全双工的,即双方的数据读写可以通过一个连接进行。
TCP协议的这种连接是一对一的,不能广播和多播,无连接的UDP协议非常适合广播和多播
字节流的概念:发送端执行的写操作次数和接收端执行的读操作次数之间没有任何数量关系(UDP则相反)。
在这里插入图片描述
TCP传输时是可靠的:采用发送应答机制超时重传机制。TCP协议还会接受到的TCP报文段重排、整理,在交付给应用层。
UDP协议和IP协议一样,提供不可靠的服务。他们都需要上层协议来处理数据确认和超时重传。

TCP头部结构

TCP固定头部结构

在这里插入图片描述
16位端口号:告知主机该报文段的源端口号目的端口号。客户端通常使用系统自动选择的临时端口号,而服务器则使用知名服务端口号(都定义在/etc/services文件中)。
32位序号:一次TCP通讯过程中某一个传输方向上的字节流的每个字节的编号。发送的第一个TCP报文段中,序号值被系统初始化为某个随机值ISN(Initial Sequence number)。
32位确认号:用作对另一方发送来 的TCP报文段的响应,其值是收到的TCP报文段的序号值加1.
4位头部长度:标识该TCP头部有多少32bit字。TCP头部最长60字节。
6位标志位
URG:表示紧急指针是否有效。
ACK:表示确认号是否有效。携带ACK标志的TCP报文段为确认报文段。
PSH:提示接收端应用程序应该立即从TCP接收缓冲区中读走数据。
RST:表示要求对方重新建立连接。携带RST标志的TCP报文段为复位报文段。
SYN:表示请求建立一个连接。携带SYN标志的TCP报文段为同步报文段。
FIN:表示请求建立一个连接。携带FIN标志的TCP报文段为结束报文段。
16位窗口大小:是TCP流量控制的一个手段。指的是接收通告窗口(Receiver Window,RWND)。它告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度。
16位校验和:由发送端填充,接收端对TCP报文段执行CRC算法以检验TCP报文段在传输过程中是否损坏(检验头部和数据部分)。
16位紧急指针(紧急偏移):是一个正的偏移量。它和序号字段的值相加表示最后一个紧急数据的下一字节的序号。

TCP头部选项

最多包含40字节。
在这里插入图片描述
kind:说明选项的类型。
length:指定选项的总长度。
info:选项的具体信息。
在这里插入图片描述
kind=0 选项表结束选项。
kind=0 空操作(nop)选项。
kind=2 最大报文段长度(Max Segment Size,MSS)选项用在TCP连接初始化时,通常为MTU-40,以太网而言为1460字节。
kind=3 窗口扩大因子选项用在TCP连接初始化时。假设N为TCP头部 中的接收通告窗口大小,M为窗口扩大因子(移位数)M的取值范围为0~14。实际接收通告窗口大小是N左移M位。可通过修改/proc/sys/net/ipv4/tcp_window_scaling内核变量来启用或关闭扩大因子选项
MSS最大报文段长度选项和M窗口扩大因子选项只能出现在同步报文段中,否则将被忽略。
kind=4是选择性确认选项(Selective Acknowledgment,SACK)用在TCP连接初始化时使TCP模块只重新发送丢失的TCP报文段。通过修改/proc/sys/net/ipv4/tcp_sack内核变量来启用或关闭选择性确认选项。
kind=5是SACK实际工作的选项。该选项告诉发送方本端已经收到并缓存的不连续的数据块。最多包函数4个不连续块(8个块边沿)
kind=8是时间戳选项。提供了较为准确的计算通讯双方之间的回路时间(Round Trip Time,RTT),通过修改/proc/sys/net/ipv4/tcp_timestamps内核变量来开启或关闭时间戳选项。

使用tcpdump观察TCP头部信息

TCP连接的建立和关闭

三此握手建立连接,四次挥手断开连接。
在这里插入图片描述

使用 tcpdump观察TCP连接的建立和关闭

半关闭状态

在这里插入图片描述

连接超时

TCP模块一共执行5次重连操作,这是由/proc/sys/net/ipv4/tcp_syn_retries内核变量所定义的。每次重连的超时时间都增加一倍。在5次重连均失败的情况下,TCP模块放弃连接并通知应用程序。

3.4 TCP状态转移

在这里插入图片描述

3.4.1 TCP状态转移总图

在这里插入图片描述

3.4.2 TIME_WAIT状态

在这个状态,客户端连接要等待一段长为2MSL(Maximum Segment Life,报文段最大生存时间)的时间(RFC1122建议值为2 min),才能完全关闭。
TIME_WAIT状态存在的原因
1.可靠地终止TCP连接(防止报文段7丢失,服务器将再次发送结束报文段)。
2.保证让迟来的TCP报文段有足够的时间被识别并丢弃(防止相似连接incarnation化身的立即建立)。
客户端一般使用系统自动分配的临时端口号来建立连接,一般可以立即重启。
服务器总是使用同一个知名服务端口号,一般不能立即重启。可以通过socket选项SO_REUSEADDR来强制进程立即使用处于TIME_WAIT状态的连接占用的端口。

3.5复位报文段

3.5.1 访问不存在的端口

sudo tcpdump -nt -i ens33 port 54321#仅抓取发送至和来自54321端口的TCP报文段$ telnet 192.168.1.10854321
Trying 192.168.1.108.. .
telnet: connect to address 192.168.1.108: Connection refused
#tcpdump抓取到的TCP报文段
1. IP 192.168.1.109.42001 > 192.168.1.108.54321: Flags [S], seq 21621375,win14600,length 0
2. IP 192.168.1.108.54321 > 192.168.1.109.42001: Flags [R. ],seq 0,ack21621376,win 0,length 0

3.5.2 异常终止连接

给对方发送一个复位报文段,则发送端所有排队等待发送的数据都将被丢弃
应用程序可以使用socket选项SO_LINGER来发送复位报文段,以异常终止一个连接。

3.5.3 处理半打开连接

客户端(或服务器)往处于半打开状态的连接写入数据,则对方将回应一个复位报文段。

3.6 TCP交互数据流

TCP携带的应用程序数据:
1、交互数据:仅包含很少的字节,对实时性要求高,eg:telnet、ssh
2、成块数据:通常为TCP报文段允许的最大数据长度。eg:ftp
Nagle算法解决广域网上的交互数据导致的拥塞。
它要求一个TCP连接的通讯双方在任意时刻都最多只能发送一个未被确认TCP报文段。

TCP成块数据流

3.8 带外数据

带外(Out of Band,OOB),用于迅速通告对方本端发生的重要事件。
带外数据比普通数据(带内数据)有更高的优先级。
带外数据很少见,已知的仅有telnet、ftp等远程非活跃程序。
后文也将TCP紧急数据称为带外数据。
在这里插入图片描述
如果我们给TCP连接设置了SO_OOBINLINE选项,则带外数据将和普通数据一样 被TCP模块存放在TCP接收缓冲区。

3.9 TCP超时重传

Linux有两个重要的内核参数与TCP超时重传相关:/proc/sys/net/ipv4/tcp_retries1/proc/sys/net/ipv4/tcp_retries2分别指定在底层IP接管之前TCP最少执行的重传次数(默认值是3)和连接放弃前TCP最多可以执行的重传次数(默认值是15)(一般对应13~ 30 min)。

3.10拥塞控制

3.10.1 拥塞控制概述

拥塞控制:TCP模块致力于提高网络利用率,降低丢包率,并保证网络资源对每条数据流的公平性。
/proc/sys/netipv4/tcp_congestion_control文件指示机器当前所使用的拥塞控制算法。
拥塞控制的最终受控变量是发送端向网络一次连续写人(收到其中第一个数据的确认之前)的数据量,我们称为SWND (Send Window,发送窗口)。不过,发送端最终以TCP报文段来发送数据,所以SWND限定了发送端能连续发送的TCP报文段数量。这些TCP报文段的最大长度(仅指数据部分)称为SMSS(Sender Maximum Segment Size,发送者最大段大小),其值一般等于MSS。
RWND(接收通告窗口)控制发送端的SWND(发送窗口)。但这显然不够,所以发送端引人了一个称为拥塞窗口(Congestion Window,CWND)的状态变量。实际的SWND值是RWND和CWND中的较小者。图3-11显示了拥塞控制的输人和输出(可见,它是一个闭环反馈控制)。

在这里插入图片描述

3.10.2 慢启动和拥塞避免

TCP连接建立好之后,CWND将被设置成初始值IW(Initial Window),其大小为2~4个SMSS。但新的Linux内核提高了该初始值,以减小传输滞后。此时发送端最多能发送IW字节的数据。此后发送端每收到接收端的一个确认,其CWND就按照式(3-1)增加:

CWND+=min (N,SMSS)         (3-1)

其中N是此次确认中包含的之前未被确认的字节数。这样一来,CWND将按照指数形式扩大,这就是所谓的慢启动。慢启动算法的理由是,TCP模块刚开始发送数据时并不知道网络的实际情况,需要用一种试探的方式平滑地增加CWND的大小。

但是如果不施加其他手段,慢启动必然使得CWND很快膨胀(可见慢启动其实不慢)并最终导致网络拥塞。因此TCP拥塞控制中定义了另一个重要的状态变量:慢启动门限( slow start threshold size,ssthresh)。当CWND的大小超过该值时,TCP拥塞控制将进入拥塞避免阶段

拥塞避免算法使得CWND按照线性方式增加,从而减缓其扩大。RFC 5681中提到了如下两种实现方式
(1)每个RTT时间内按照式(3-1)计算新的CWND,而不论该RTT时间内发送端收到多少个确认。
(2)每收到一个对新数据的确认报文段,就按照式(3-2)来更新CWND。

CWND+=SMSS*SMSS/CWND               (3-2)

在这里插入图片描述

发送端判断拥塞发生的依据有如下两个:
(1)传输超时,或者说TCP重传定时器溢出。
(2)接收到重复的确认报文段(用快速重传和快速回复解决)。
如果发送端检测到拥塞发生是由于传输超时,即上述第–种情况,那么它将执行重传并做如下调整:

ssthresh=max(FlightSize/22*SMSS)               (3-3)
CWMD<=SMSS

其中FlightSize是已经发送但未收到确认的字节数。这样调整之后,CWMD将小于SMSS,那么也必然小于新的慢启动门限值 ssthresh (因为根据式(3-3),它一定不小于SMSS的2倍),故而拥塞控制再次进入慢启动阶段。

3.10.3 快速重传和快速修复

1)当收到第3个重复的确认报文段时,按照式(3-3)计算ssthresh,然后立即重传丢失的报文段,并按照式(3-4)设置CWND。

CWND=ssthresh+3*SMSS              (3-4)

2)每次收到1个重复的确认时,设置CWND=CWND+SMSS。此时发送端可以发送新的TCP报文段(如果新的CWND允许的话)。
3)当收到新数据的确认时,设置CWND=ssthresh ( ssthresh是新的慢启动门限值,由第一步计算得到)。
快速重传和快速恢复完成之后,拥塞控制将恢复到拥塞避免阶段,这一点由第3步操作可得知。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

<lumen>

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值