• 进入"运维那点事"后,希望您第一件事就是阅读“关于”栏目,仔细阅读“关于Ctrl+c问题”,不希望误会!

传输层之TCP协议

网络基础 彭东稳 9年前 (2015-09-22) 31643次浏览 已收录 1个评论

一、TCP协议的特点

  • TCP是一种可靠的、面向连接的字节流服务。源主机在传送数据前需要先和目标主机建立连接。
  • TCP提供可靠交付的服务,也就是说,通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序列到达。且提供流量控制和拥塞控制。
  • 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的。
  • TCP提全双工通信,允许通信双方的应用进程在任何时候都能发送数据。TCP连接的两端都设有发送缓存和接收缓存用来临时存放双向通信的数据。
  • 面向字节流,TCP中的“流”指的是流入到进程或从进程流出的字节序列。面向字节流的含义是:虽然应用程序和TCP的交互是以此一个数据块,但TCP把应用程序交下来的数据看成仅仅是一连串的无结构的字节流。TCP并不知道所传送的字节流的含义。

二、TCP报文格式

传输层之TCP协议

Source/Dest Port

源/目标端口号字段:占16比特。TCP协议通过使用”端口”来标识源端和目标端的应用进程。端口号可以使用0-65535之间的任何数字。在收到服务请求时,操作系统动态地为客户端的应用程序分配端口号。在服务器端,每种服务在”众所周知的端口”(Well-Know Port)为用户提供服务。

Sequence number

顺序号字段:占32比特。用来标识从TCP源端向TCP目标端发送的数据字节流,它表示在这个报文段中的第一个数据字节。 

Acknowledgement Number

确认号字段:占32比特。只有ACK标志为1时,确认号字段才有效。它包含目标端所期望收到源端的下一个数据字节的序号。

Header Length

头部长度字段:占4比特。给出头部占32比特的数目。没有任何选项字段的TCP头部长度为20字节;最多可以有60字节的TCP头部。

保留

占6位,保留为今后使用,但目前应置为0。

标志位字段(U、A、P、R、S、F)

占6bit各Bit的含义如下:

URG:紧急指针(urgent pointer)有效或无效。

ACK:说明确认号是否有效;1有效,0无效。

PSH:推送表示接收方应该尽快将这个报文段交给应用层不能再缓冲中停留,内核优先处理的报文。

RST:重建连接。

SYN:发起一个连接。

FIN:释放一个连接。

Windows size

窗口大小字段:占16比特。窗口指的是发送本报文段的一方的接收窗口就(不是自己的发送窗口)。窗口值告诉对方:从本报文段首部中的确认好算起,接收方没目前允许对方发送的数据量。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。

Tcp checksum TCP

校验和字段:占16比特。对整个TCP报文段,即TCP头部和TCP数据进行校验和计算,并由目标端进行验证。

Urgent Pointer

紧急指针字段:占16比特。它是一个偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。URG为1有效。

Options

选项字段:占32比特。可能包括”窗口扩大因子”、”时间戳”等选项。

Data

数据段:承载应用层的数据。

三、UDP数据段格式

UDP是一种不可靠的、无连接的数据报服务。源主机在传送数据前不需要和目标主机建立连接。数据被冠以源、目标端口号等UDP报头字段后直接发往目的主机。这时,每个数据段的可靠性依靠应用层协议来保证。在传送数据较少、较小的情况下,UDP比TCP更加高效。

传输层之TCP协议

源/目标端口号字段:占16比特。作用与TCP数据段中的端口号字段相同,用来标识源端和目标端的应用进程。

长度字段:占16比特。标明UDP头部和UDP数据的总长度字节

校验和字段:占16比特。用来对UDP头部和UDP数据进行校验。和TCP不同的是,对UDP来说,此字段是可选项,而TCP数据段中的校验和字段是必须有的。

四、套接字

前面说过,TCP的每一条连接都有两个端点,那么TCP连接的端点是什么呢?不是主机,不是主机的IP地址,不是应用进程,也不是传输层的协议端口。TCP连接的端点叫做套接字(socket)。端口号拼接到IP地址即构成了套接字。因此套接字的表示方法是在在点分十进制的IP地址后面写上端口号,中间用冒号或逗号隔开。例如,若IP地址是192.168.10.1而端口号是80,那么得到的套接字就是192.168.10.1:80

总之,TCP连接就是由协议软件所提供的一种抽象,虽然有时为了方便,我们也可以说,在一个应用进程和另一个应用进程之间建立了一条TCP连接,但一定要记住:TCP连接的端点是套接字,即IP地址和端口号。也还应记住:同一个IP地址可以有多个不同的TCP连接,而同一个端口号也可以出现多个不同的TCP连接中。

五、TCP的连接建立

下图画出了TCP的建立连接的过程,主机A运行的事TCP客户端程序,而B主机运行的事服务器端程序。最初两端的TCP进程都处于CLOSED(关闭)状态。另外A是主动打开而B是被动打开。

传输层之TCP协议

首先,B服务器端会先创建传输控制块TCB(transmission control block)传输控制块存储了每一个连接中的一些重要信息,入TCP连接表,到发送和接收缓存的指针等等,准备接收客户端进程的连接请求。然后服务器进程就处于LISTEN(监听)状态,等待客户端的连接请求。如有,即作出响应。

TCP的建立连接的过程称为3次握手,如上图所示:

1)A的TCP客户进程也是首先创建传输控制模块TCB,然后向B发出连接请求报文段,其首部中的同步位SYN=1,并选择序号seq=x,表明传送数据时的第一个数据字节的序号是x。这时,TCP客户进程进入SYN-SENT(同步已发送)状态。

2)B的TCP收到连接请求报文段后,如同意,则发回确认。B在确认报文段中应使SYN=1,使 ACK=1,其确认号ack=x+1,自己选择的序号seq=y。这时,TCP服务器进程进入SYN-RCVD(同步收到)状态。

3)A收到此报文段后向B给出确认,其ACK=1,确认号ack=y+1。A的TCP通知上层应用进程,连接已经建立。此时双方的TCP进程状态都是ESTABLISHED(已建立连接)标识建立连接成功。

其中A为什么还要发送一次确认呢?这主要是为了防止“已失效的连接请求报文段”突然又传送到了B,因而产生错误。已失效的比如A发出连接请求但是由于在网络结点长时间滞留了,以致延误到连接释放以后的某个时间才到达B。本来这事一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误认为是A又发出一次新的连接请求。于是就向A发出确认报文段,同意建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了。由于现在A并没有发出建立连接的请求,因此不会理睬B的确认,也不会向B发送数据。但B却认为新的传输连接已经建立了,并一直等待A发来数据。B的许多资源就这样浪费了。

下面给出了一个TCP建立连接的数据报,分析一个TCP建立连接的三次握手过程。如下:

第一次握手:192.168.1.116发送位码syn=1,随机产生seqnumber=3626544836的数据包到192.168.1.123, 192.168.1.123由SYN=1知道192.168.1.116要求建立联机;

第二次握手:192.168.1.123收到请求后要确认联机信息,向192.168.1.116发送acknumber=3626544837,syn=1,ack=1,随机产生seq=1739326486的包;

第三次握手:192.168.1.116收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,192.168.1.116会再发送ack number=1739326487,ack=1,192.168.1.123收到后确认seq=seq+1,ack=1则连接建立成功

六、TCP的连接释放

TCP连接释放过程比较复杂,仍结合双方状态的改变来说明连接释放的过程。如下图画出了释放过程,

传输层之TCP协议

数据传输结束后,通信的双方都可释放连接,现在A和B都处于ESTABLISHED状态。A的应用进程先向其TCP发出连接释放报文段,并停止在发送数据,主动关闭TCP连接。

1)A把连接释放报文段首部的FIN=1,其序号seq=u,等待 B 的确认。这时A进入FIN-WAIT-1(终止等待1)状态,等待B确认。

2)B收到连接释放报文后即发出确认,确认号ack=u+1,而这个报文段自己的序号seq=v。然后B就进入CLOSE-WAIT(关闭等待)状态。TCP服务器进程通知高层应用进程。从A到B这个方向的连接就释放了,TCP连接处于HALF-CLOSE(半关闭)状态。B若发送数据,A仍要接收。

3)A收到来自B的确认后,就进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段。若B已经没有要向A发送的数据,其应用进程就通知 TCP 释放连接。这时B发出的连接释放报文段必须是FIN=1,现假定B的序号为W(在半关闭状态B可能又发送了一些数据)。B还必须重复上次已发送过的确认号ack=u+1。这时B就进入LAST-ACK(最后确认)状态,等待A的确认。

4)A在收到B的连接释放报文后,必须对此发出确认。在确认报文段中把ACK置1,确认号ack=w+1,而自己的序号是seq=u+1。然后进入到TIME-WAIT(时间等待)状态。请注意,现在TCP连接还没有释放掉。必须经过时间等待计时器(TIME-WAIT TIMER)设置的时间2MSL后,A才进入到CLOSED状态。时间MSL叫做最长报文段寿命(maximum segment lifetime),RFC 793建议设为2分钟。但这完全是从工程上来考虑,对于现在的网络,MSL=2分钟可能时间太长了一些。因此TCP允许不同的实现可根据具体情况使用更小的MSL值。因此,从A进入到TIME-WAIT状态后,要进过4分钟才能进入到CLOSED状态,才能开始建立下一个新的连接,当A撤销响应的传输控制块后,就结束了这次的TCP连接。

为什么A主机在TIME-WAIT状态必须等待2MSL的时间呢?

第一,为了保证A发送的最后一个ACK报文段能够到达B。这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的B收到对已发送的FIN+ACK报文段的确认。B会超时重传这个FIN+ACK报文段,而A就能在2MSL时间内收到这个重传的FIN+ACK报文段。接着A重传一次确认,重新启动2MSL计时器。最后,A和B都正常进入到CLOSED状态。如果A在TIME-WAIT状态不等待一段时间。那么就无法收到B重传的FIN+ACK报文,因而也不会再发送一次确认报文,这样B就无法按照正常步骤进入CLOSED状态。

TCP有一个特别的概念叫做half-close,这个概念是说由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

七、TCP有限状态机

在TCP连接的建立和释放中也都给出了TCP的各种状态信息,这里为了更加清晰地看出TCP连接的各种状态之间的关系,给出了下图:

传输层之TCP协议

这个图给出了TCP的有限状态机,图中每一个方框即TCP可能具有的状态。每个方框中的大写英文字符串是TCP标准的所使用的TCP连接状态名。状态之间的箭头表示肯那个发生的状态变迁。箭头旁边的字,表面引起这种变迁的原因,或表面发生状态变迁后又出现什么动作。注意:图中有三种不同的箭头,粗实线箭头表示对客户端进程的正常变迁,粗虚线箭头表示对服务器进程的正常变迁。另一种细线箭头表示异常变迁。

状态解释:

CLOSED:关闭状态。

LISTEN:侦听来自远方的TCP端口的连接请求。

SYN-SENT:再发送连接请求后等待匹配的连接请求。

SYN-RECEIVED:再收到和发送一个连接请求后等待对方对连接请求的确认。

ESTABLISHED:代表一个打开的连接。

FIN-WAIT-1:发送FIN之后的状态。

CLOSING:接收远程TCP连接中断的确认。

FIN-WAIT-2:接收到远程TCP连接中断的请求。

TIME-WAIT:等待足够的时间2MSL以确保远程TCP接收到连接中断请求的确认。

CLOSE-WAIT:等待本地用户发的连接中断确认到连接中断请求。

LAST-ACK:等待原来的发向远程TCP的连接中断请求的确认。

<延伸>

https://www.cnblogs.com/qcrao-2018/p/10182185.html


如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。
喜欢 (10)
[资助本站您就扫码 谢谢]
分享 (0)

您必须 登录 才能发表评论!

(1)个小伙伴在吐槽
  1. 看来你对网络情有独钟啊 哈哈,网络原理的学习是挺有意思的。
    彭东稳2016-03-10 18:47 Windows 7 | Chrome 48.0.2564.116