TCP协议


1.特点

1.1 支持面向连接的传输服务

如果将UDP协议提供的服务比作一封邮件的话,那么TCP协议所能提供的服务相当于语音聊天,必须要通信双方建立连接。

面向连接对提高系统数据传输的可靠性是很重要的,使用TCP传输数据之前,必须在源进程端口与目的进程端口之间建立一条TCP传输连接。用双方端口号来标识。TCP建立在不可靠的网络层 IP 协议上,IP 协议不能提供任何可靠性保障机制,因此TCP 协议的可靠性需要自己解决。

1.2 支持字节流的传输

流(stream)相当于是一个管道(水管),从一端放入什么,另一端可以照原样取出。描述了一个不出现 :丢失、重复、乱序的数据传输过程。TCP 协议将数据看成是一连串的、无结构的字节流

如果用户是通过键盘输入数据,应用进程将字符逐个提交给发送端。如果数据是从文件得到,那么数据可能是逐行或逐块交付发送端。

为了支持字节流传输,发送端和接收端都需要使用缓存。发送端将几个写操作组合成一个报文的,提交给 IP 协议,由 IP 协议封装成 IP 分组之后传输到接收端,

1.3 支持全双工通信

由于通信双方都设置有发送和接收的缓冲区,TCP 协议允许通信双方在任何时候都可以发送数据

1.4 支持同时建立多个并发的TCP连接

TCP 协议需要支持同时建立多个连接,这个特点在服务端表现的更为突出。一个服务器必须同时处理多个客户端的访问。例如,一个Web服务器的套接字为“ 141.8.22.51:80 ”,同时有三个客户端需要访问这个服务器,它们的套接字分别为“ 202.1.12.5:30001 “ “ 242.1.12.5:300022 “ “ 212.1.12.5:300023 “则服务器端需要同时建立三个 TCP 连接。

也支持一个客户端与多个服务器同时建立多个 TCP 连接。

1.5 支持可靠的传输服务

TCP 协议使用确认机制检查数据是否安全和完整,并且提供拥塞控制功能。对发送和接收的数据进行跟踪、确认和重传。

但是 TCP 协议是建立在不可靠的网络层 IP 协议之上,一旦 IP 协议及以下层出现传输错误,TCP 协议只能不断进行重传,可靠性会受到底层限制。

2.报文格式

窗口

窗口字段长度为16位,表示以字节(B)为单位的窗口大小。

由于接收端的接收缓冲区是受到限制的,因此需要设置一个窗口字段,表示下一次传输接收端还有多大的接收容量。窗口字段值是准备接收下一个 TCP报文段的接收端,通知即将发送报文段的发送端,下一次最多可以发送报文段的字节数。

发送端将根据接收端通知的窗口值调整自己的发送窗口值大小。

窗口字段值是动态变化的。

主机A 发给主机 B的TCP报头中确认号是 502,窗口值 1000。表示:下一次主机B要向主机A发送的 TCP,字段第一字节号应该是 502,字段最大长度是 1000,最后一个字节号最大是 1501。

序号

序号字段长度位32位

TCP 是面向字节流的,它需要为发送字节流中的每个字节都按顺序编号。

TCP连接建立时,每方都需要使用随机数产生器,生成一个初始序号。

不能为0。避免因TCP连接非正常断开而可能引起的混乱。如果在连接突然中断时,可能有一个或两个进程同时等待对方的确认应答,而这个时候有一个新连接的序号也是从0开始,那么接收进程就有可能认为是对方重传的报文,这样就可能造成连接过程的错误。

ACK(确认位)

在TCP连接建立后发送的所有报文段的ACK位都要置 1。

SYN(同步位)

在连接建立时用来同步序号。例如 SYN=1,ACK=0时,表示这是一个连接建立请求报文,同意建立连接的响应报文:SYN=1,ACK=1。

3. 连接建立与释放

3.1 三次握手

3.1.1

最初,客户端TCP 进程是处于 CLOSE 状态。准备发起TCP连接时,进入 SYN-SEND 状态,向处于LISTEN 状态的服务器端 TCP 进程发送第一个控制位 SYN = 1 的”连接建立请求报文“,不携带数据字段,但需要给报文一个序号 seq=x。 SYN=1 seq=x

3.1.2

服务器端接收到” 连接建立请求报文“之后,如果同意建立连接,则向客户端发送第二个控制位 SYN=1, ACK=1 的 ” 连接建立请求确认报文 “。确认号 ack = x + 1,表示是对第一个” 连接建立请求报文“(序号 seq=x)的确认。同样不携带任何数据字段,但是需要给报文一个序号 seq=y。这时服务器进入 SYN-RCVD(准备接收)状态SYN=1 ACK=1 seq=y ack=x+1

3.1.3

客户端发送第三个控制位 ACK=1 ” 连接建立请求确认报文 “。由于该报文是对” 连接建立请求确认报文”(seq=y)的确认,因此确认序号 ack=y+1。同样不携带数据字段,但需要给一个序号,仍为 x+1 。ACK=1 seq=x+1 ack =y+1。这时客户端进入 ESTABLISHED(已建立连接)状态。服务器端在接收到ACK报文之后也进入 ESTABLISHED (已建立连接)状态。

三次握手完成。TCP连接建立。

3.1.4 为什么需要第三次握手?

主要是防止已经失效的连接请求报文段突然又传回到服务端而产生错误:

  1. 客户端发出的第一个连接请求报文段,
  2. 但是由于某些原因在某个网络节点滞留了很长时间,客户端一直等不到确认报文,于是客户端再次发出一次新的连接请求,并成功收到服务端确认,建立了连接。
  3. 之前的请求报文段并没有丢失,延误到客户端与服务端连接释放后才到达服务端,本来这个请求已经失效了,但是服务端收到此请求报文段后,误以为是客户端发出的新的请求连接,于是服务端又向客户端发出确认报文段。
  4. 假如不采用三次握手,那么只要服务端发出确认,连接就建立了。
  5. 但是客户端并没有发出连接建立的请求,因此不会理会服务端的确认,也不会向服务端发出数据。
  6. 而服务端以为却一直在等待客户端发来数据,这样服务端的许多资源就白白浪费了
  7. 常用三次握手可以防止上诉现象发生。客户端不向服务端发出确认请求,服务端就不会建立连接。

3.2 报文传输

TCP传输连接建立之后,双方可以使用这个连接,进行全双工的字节流传输。

为了保证TCP工作正常、有序的进行,TCP在服务器端设置了保持计时器(keep timer),用来防止TCP连接处于长时间空闲。当服务器端收到客户端的报文时,就保持计时器复位。如果没有收到客户端的信息,他就发送探测报文。如果发送10个探测报文(每个相隔 75s)还没有响应,就假设客户端出现故障,终止该连接。

3.3 四次挥手

3.3.1

客户端主动提出释放TCP连接,进入 FIN-WAIT-1(释放等待-1)状态。向服务器发送第一个控制位FIN=1,的 ” 连接释放请求报文 ”,提出连接释放请求,停止发送数据。不携带任何数据字段。但是需要给报文一个序号。 FIN=1,seq=u 。u等于客户端发送的最后一个字节的序号加1。

3.3.2

服务器端收到之后,需要向客户发送 “ 连接释放请求确认报文 ”,表示对报文的确认, ack=u+1。这个 “ 连接释放请求报文 ” 的序号 v 等于服务器发送的最后一个字节序号加1。 ACK=1,seq=v,ack=u+1

TCP服务器进程向高层应用进程通知客户请求释放TCP连接,客户到服务器的TCP连接断开,但是服务器到客户的TCP连接还没有断开,如果服务器还有数据报文需要发送时,它还可以继续发送直至完毕。这种状态称为半关闭(helf-close)状态。这个状态需要持续一段时间。

客户在接收到服务器发送的ACK报文之后进入 FIN-WAIT-2状态服务器进入CLOSE-WAIT状态

3.3.3

服务器的高层应用程序已经没有数据需要发送时,它会通知TCP可以释放连接,这时服务器向客户发送 “ 连接释放请求报文 ”。报文的序号(假定为w),取决于在半关闭状态时,服务器端是否发送过数据报文。服务器端经过 LAST-ACK状态之后转回到LISTEN(收听)状态ACK=1,FIN=1,seq=w,ack=u+1。

3.3.4

客户接收到FIN报文之后,向服务器发送 “ 连接释放请求确认报文 ”,ACK=1,seq=u+1,ack=w+1

3.3.5 为什么TCP的连接的建立只需要三次握手,而连接的释放需要四次呢?

因为服务端在LISTEN状态下,收到建立请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端

而连接关闭时,当收到对方的FIN报文时,仅仅表示客户端没有需要发送的数据了,但是还能接收数据。服务端上层的应用程序未必数据已经全部发送给对方了,此时服务端可以立即关闭,也可以将应该发送的数据全部发送完毕后,再发送FIN报文给客户端来表示同意现在关闭连接。

从这个角度而言,服务端的ACK和FIN一般都会分开发送。从而导致多了一次。

3.4 时间等待计时器

为了保证TCP连接释放过程正常的进行,TCP设置了时间等待计时器(TIME-WAIT Timer)。当TCP关闭一个连接时,它并不认为这个连接马上就真正的关闭。这时,客户端进入TIME-WAIT状态,需要再等待两个最长报文寿命(maximum segment lifetime,MSL)时间之后,才真正进入CLOSE(关闭)状态

四次挥手之后,确认双方已经同意释放连接,客户端仍需要采取延迟2MSL时间,确保服务器在最后阶段发送给客户端的数据,以及客户端发送给服务器的最后一个ACK报文都能正确的被接收,防止因个别报文传输错误导致连接释放失败

4.滑动窗口与确认、重传机制

4.1 滑动窗口

TCP协议使用以字节为单位的滑动窗口协议(Sliding-Windows Protocol),来控制字节流的发送、接收、确认、重传过程。

  1. TCP使用两个缓存和一个窗口控制字节流的传输过程

    发送端的TCP有一个缓存,用来存储应用进程准备发送的数据。对这个缓存设置一个发送窗口

    接收端也有一个缓存,将正确接收到字节流写入缓存,等待应用进程读取。也有一个接收窗口。

    只要发送窗口值不为0就可以发送报文段。发送窗口的大小取决于接收窗口的大小发送端每一次能够连续发送字节数取决于发送窗口的大小不能超过接收窗口值,发送端可以根据自身的需要来决定。

    接收窗口值等于接收缓存还可以继续接收的字节流的大小。由接收端根据接收缓存剩余空间的大小,以及应用进程读取数据的速度决定。

  2. 接收端通过TCP报头通知发送端,已经正确接收的字节号,以及发送端还能够连续发送的字节数

  3. 虽然TCP协议是面向字节流的,但是它不可能每次传送一个字节,就对这个字节进行确认。它是将字节流分成段,一个段的多个字节打包成一个TCP报文段一起传送、一起确认。TCP协议通过报头的“序号”来标识发送的字节,用“确认号”表示哪些字节已经被正确的接收。

4.1.2 字节流传输状态

为了达到利用滑动窗口协议控制差错的目的,TCP协议引入了“字节流传输状态”的概念。为了对正确传输的字节流进行确认,必须对字节流的传输状态进行跟踪:

假设发送的第一个字节的序号是1。

  1. 第一类:已经发送,且已得到确认的字节。假设序号为19之前的字节已经被接收端正确的接收,并且发送端发送了确认信息。1-19的字节属于第一类。
  2. 第二类:已经发送,但未收到确认的字节。
  3. 第三类:尚未发送,但是接收端表示接收缓冲区已经准备好,如果发送端准备好就可以立即发送这些字节。
  4. 第四类:尚未发送,且接收端也未做好接收准备的字节。
4.1.3 发送窗口与可用窗口

发送端每一次能够连续发送字节数取决于发送窗口的大小。

发送窗口的长度等于第二类与第三类字节数之和。

可用窗口长度等于第三类字节数。如果没有任何问题,发送端可以立即发送可用窗口的字节。

接收端确认发送窗口的字节,为保持发送窗口值不变,需要将窗口向左滑动(例如从序号1 移动到 20)。

4.2 容错控制

TCP协议通过滑动窗口机制来跟踪和记录发送字节的状态,实现差错控制功能。

  1. TCP协议的设计思想是让应用进程将数据作为一个字节流传送,而不是限制应用层数据的长度。应用进程不需要考虑发送数据的长度,由TCP协议来负责将这些字节分段打包
  2. 发送端利用已建立的TCP连接,将字节流传送到接收端的应用进程,并且是顺序的,没有差错、丢失、重复的
  3. TCP协议发送的报文是交给 IP 协议传输的,IP协议只能提供尽力而为的服务,IP分组在传输过程中出错是不可避免的,TCP协议必须提供差错控制、确认、重传功能,以保证接收的字节流是正确的。

4.3 选择重传策略

上面我们没有考虑到报文段丢失的情况,但是在Internet中,报文段丢失是不可避免的,会造成接收的字节流序号不连续的现象。

接收字节流序号不连续的处理方法有两种:拉回、选择重传

4.3.1 拉回

在丢失第二个报文段时,不管之后的报文段接收是否正确,都要求从第二个报文段开始,重传后面的所有的报文段。显然,拉回方式发效率是很低的。

4.3.2 选择重传

选择重传(selective ACK,SACK),如果收到字节流序号不连续时,如果这些字节的序号都在接收窗口之内,则首先完成接收窗口内字节的接收,然后将丢失的字节序号通知发送端,发送端只需要重传丢失的报文段,而不需要重传已经接收的报文段。

4.4 重传计时器

TCP使用重传计时器(retransmission timer)来控制报文确认与等待重传的时间。当发送端发送一个报文时,首先将它的一个报文的副本放入重传队列,同时启动一个重传计时器。重传计时器设定一个值,例如400ms,然后开始倒计时。时间结束前收到确认,表示传输成功,否则说明传输失败,准备重传该报文。

4.4.1 影响超时重传的元素

设定重传计时器的时间值时很重要的。如果设定值过低,可能出现已被接收端正确接收的报文被重传,造成接收报文重复的现象。如果设定值过高,造成一个报文已经丢失,而发送端长时间等待,造成效率降低的现象。

  1. 如果一个主机同时与其他两个主机建立两条TCP连接,那么它就需要分别为每个连接启动一个重传计时器。如果一个用于本地局域网中传输文本文件,另一个用于Internet远程访问Web服务,那么两个TCP报文的往返时间相差很大。因此,需要对不同的TCP连接设定不同的重传计时器的时间。
  2. 由于Internet在不同时间段的用户数量变化很大,流量与传输延迟变化也很大,报文传输延迟也不会相同。

正是由于这些原因,为TCP连接确定合适的重传定时器数值是很可能的。TCP不会采用简单的静态方法,必须采用动态的自适应的方法。根据端对端报文往返时间的连续测量,不断调整和设定重传定时器的超时重传时间。

4.5超时重传时间的选择

略。。。(写不动了,下次再补吧)

5.滑动窗口与流量控制、拥塞控制

5.1 TCP窗口与流量控制

研究流量控制(flow control)算法的目的是控制发送端发送速率,使之不超过接收端的接收速率,防止由于接收端来不及接收送达的字节流,而出现报文段丢失的现象。滑动窗口协议可以利用TCP报头中窗口字段,方便的实现流量控制。


  TOC