概述
TCP被作为一种运行在分组交换网络(以及它们的互联系统)上的高可靠的主机到主机协议。TCP是面向连接的、端到端的通用协议,却对下层协议的假设甚少(可以是多网络环境,只要求一个不可靠的报文服务),一般用于互联网上不同主机的进程间通信。 现行协议版本被IETF标准化为RFC-793。
虽然TCP主要运行在互联网的IP协议层之上,但原则上,TCP能够在多种通信系统上进行操作,从硬连线连接到分组交换或电路交换系统。
概述
互联网系统元素
Internet环境由连接在通过网关互联的网络上的主机组成。为了在不同主机的进程间通信,网络上运行着多层的协议。
分组 是主机以及它所在网络上一次交换的数据。 主机 是连在网络上的计算机,是分组的源和目标。 进程 是主机上的活跃元素。
一个进程可能需要独立的多个连接,于是每个进程可以有多个端口来和其他进程通信。
操作模型
进程通过调用TCP(以数据缓存作为参数)进行数据传输。TCP将数据打包为片段(segment),调用互联网模块传输给目标TCP。接收方TCP将每个片段放在接收用户的缓存中,然后提示用户。
TCP在片段中包括控制信息,被用来确保传输数据的顺序。
每个TCP模块关联着一个提供本地网络接口的IP模块,该模块将TCP片段打包成IP数据包,并将其路由到目标IP模块或中间网关。为了在本地网络中传输该数据报,它又被嵌入到本地网络分组中。 分组交换继续做打包、分段等其他操作来递送本地网络分组给目标IP模块。
在网络间的网关上,打开本地网络分组,得到IP数据报。然后决定接下来应该发送该数据报到那个网络。此后,该数据报被打包进适合下一个本地网络的本地网络分组,路由给下一网关或最终目标。
网关可以根据需要将IP数据报切分成较小的数据报片段。切分后的片段也可能被再次切分。根据IP数据报分片的格式的设计,目标IP模块可以将分片组装为IP数据报。
目标IP模块将数据报(如果需要,先进行组装)中的数据拿出来,传送给目标TCP模块。
简单的模型中仍有很多的细节,比如服务类型。它为网关选择下一个网络的服务参数提供了信息。服务类型包括数据报的优先级,或者安全信息。这些允许主机和网关根据安全考虑,进行多安全层次的操作来分离数据报。
连接
TCP连接用一对socket来标识,且TCP连接可以向两个方向传送数据,即TCP是全双工的。同时每个端口可以任意绑定一个进程,进程只能对属于自己的端口进行初始化。
每个数据流都需要维护一些状态信息。这些信息(包括socket、序列号、窗口大小)组成一个连接。一个连接用一组socket标识。
通信之前,双方应该建立一个连接。结束通信后连接被终止或关闭,释放的资源可供他用。
为了在不可靠的Internet上建立连接和避免错误的连接初始化,TCP采用了握手机制和基于时钟的序列号。
接口
TCP应作为操作系统的一个模块。其用户接口包括OPEN
,CLOSE
,SEND
,RECEIVE
,STATUS
。这些调用就像是文件调用一样:打开、读、关闭。TCP通过IP来间接调用本地网络接口,TCP接口提供了发送(或接收)数据报给任何互联网中TCP地址的调用。
优先级与安全性
使用TCP的用户可能会指定优先级和安全性。当这些特性未被使用时,应提供默认值。
操作
TCP允许的操作包括以下几个方面:
基本数据传输
TCP能够在两个方向上传输连续的字节流,通常会把一些字节打包成片段,然后交给互联网系统进行传输。
通常TCP可以根据自己的方便,进行阻塞和转发。因此需要提供PUSH
操作,以免用户需要立即发送。该操作会导致TCP立即转发数据,但这个过程对接收方应是不可见的。
可靠性
TCP能够从传输错误中恢复,除非互联网完全断开。传输错误包括:损坏、丢失、重复、乱序。
为了实现这个目的,每个传输的字节都被标记一个序列号(SEQ),同时接收方应提供确认号(ACK)。如果确认号超时,则重发数据。在接受端,序列号用来重新排列乱序或重复的片段。数据损坏用一个校验值来处理,在接收端抛弃损坏的片段。
流控制
TCP提供了一种手段来管理发送者发送的数据量。接收者发送一个“窗口”(接下来期望接受的字节范围)给发送者,发送者在接收到进一步允许前只能发送这些字节。
多路复用
为了允许同一主机的不同进程同时使用TCP设施,TCP提供了一组端口,加上互联网通信层地址(IP),组成一个socket。一对socket唯一地标识了一个TCP连接。 而一个进程可以绑定到端口来监听网络。为了方便,将常用进程绑定到公开的确定端口。这样就可以通过公共地址来访问服务了。
对于其他非公开确定的端口,建立连接涉及到更多的动态机制。
TCP头
在传送的片段中,TCP头的位置紧接着IP头,其中提供了TCP协议规定的必要信息:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
字段说明:
Source/Destination Port
:源与目标端口。Sequence Number
:该片段中第一个数据字节的序列号。如果SYN
是1,则该序列号成为初始序列号(ISN
),第一个数据字节为ISN+1
。Acknowledgment Number
:如果ACK
是1,该字段包含期望收到的下一个序列号。Data Offset
:TCP头的长度,也就是数据的起始位置。单位为32位字。Reserved
:保留字段,必须为0。Conrol Bits
:URG
:Urgent Pointer
字段起作用。ACK
:Acknowledgment
字段起作用。PSH
:PUSH
功能。RST
:重置连接。SYN
:同步序列号。FIN
:别再发送了。
Window
:期望接收的字节长度,从Acknowledgment
开始。Checksum
:头和数据中所有16位字的反码和的反码。如果是奇数字节,最后字节后补零。计算该字段时,该字段值为0。该校验和还包含了伪头部,它包含IP地址,用来防止路由错误。Urgent Pointer
:当前紧急数据的开始位置,从序列号算起。Options
:该字段位于TCP头的末尾,可以有多个整字节。可以包括选项类型、选项长度、选项数据。Padding
:值为0的补白,确保TCP头长度为32位的整数倍。
TCP状态
一个TCP连接在整个生命周期内可能处在不同的状态,包括:
LISTEN
:等待任何远程TCP的连接请求。SYN-SENT
:发送连接请求后,等待匹配连接请求。SYN-RECEIVED
:收到并发送一个连接请求后,等待连接请求确认。ESTABLISHED
:一个打开的连接,收到的数据可以递交给用户,正常的数据传输状态。FIN-WAIT-1
:等待远程TCP的终止请求,或等待终止请求的确认。FIN-WAIT-2
:等待远程TCP的终止请求。CLOSE-WAIT
:等待本地用户的连接终止请求。CLOSING
:等待远程TCP的终止请求确认。LAST-ACK
:等待远程TCP终止请求的确认,之前发送的终止请求包含终止请求的确认。TIME-WAIT
:等待足够的时间,确保远程TCP收到了终止请求的确认。CLOSED
:没有任何连接状态。
建立连接
使用OPEN
调用来声明一个连接,同时提供本地端口、远程socket参数、以及被动等待还是主动连接。此时TCP会提供一个名称(关联着传输控制块,TCB,来存储该连接的变量的数据结构)用于后续调用。两个进程如果同时发起主动连接,它们也会正确地建立连接。这种灵活性在分布式系统中至关重要。
本地被动连接可以指定远程socket,也可以不指定。后者将会接受所有的远程socket。
建立连接采用三步握手过程,一般是一方初始化请求,另一方响应该请求。以下是一个简单的建立连接过程:
TCP A TCP B
1. CLOSED LISTEN
2. SYN-SENT --> <SEQ=100><CTL=SYN> --> SYN-RECEIVED
3. ESTABLISHED <-- <SEQ=300><ACK=101><CTL=SYN,ACK> <-- SYN-RECEIVED
4. ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK> --> ESTABLISHED
5. ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK><DATA> --> ESTABLISHED
注意第5行,此时发送了一些数据,而
SEQ
值没有变,因为ACK
报文不占用序列号空间(不同于数据和SYN
)。否则我们将需要确认ACK
。
对于同时发起连接,将会稍微复杂一些:
TCP A TCP B
1. CLOSED CLOSED
2. SYN-SENT --> <SEQ=100><CTL=SYN> ...
3. SYN-RECEIVED <-- <SEQ=300><CTL=SYN> <-- SYN-SENT
4. ... <SEQ=100><CTL=SYN> --> SYN-RECEIVED
5. SYN-RECEIVED --> <SEQ=100><ACK=301><CTL=SYN,ACK> ...
6. ESTABLISHED <-- <SEQ=300><ACK=101><CTL=SYN,ACK> <-- SYN-RECEIVED
7. ... <SEQ=101><ACK=301><CTL=ACK> --> ESTABLISHED
三路握手过程可以从旧的重复SYN
中恢复,要用到RST
字段:
TCP A TCP B
1. CLOSED LISTEN
2. SYN-SENT --> <SEQ=100><CTL=SYN> ...
3. (duplicate) ... <SEQ=90><CTL=SYN> --> SYN-RECEIVED
4. SYN-SENT <-- <SEQ=300><ACK=91><CTL=SYN,ACK> <-- SYN-RECEIVED
5. SYN-SENT --> <SEQ=91><CTL=RST> --> LISTEN
6. ... <SEQ=100><CTL=SYN> --> SYN-RECEIVED
7. SYN-SENT <-- <SEQ=400><ACK=101><CTL=SYN,ACK> <-- SYN-RECEIVED
8. ESTABLISHED --> <SEQ=101><ACK=401><CTL=ACK> --> ESTABLISHED
注意,第3行是旧的重复
SYN
,接收方在不知情的情况下仍然确认了该SYN
。此时,发送方应重置该SYN
(地5行)。然后继续新的连接。
另外一种情况是一方因故关闭,造成半开的连接。TCP的策略是发现这种情况并关闭该连接后重新由关闭方发起连接。
TCP A TCP B
1. (CRASH) (send 300,receive 100)
2. CLOSED ESTABLISHED
3. SYN-SENT --> <SEQ=400><CTL=SYN> --> (??)
4. (!!) <-- <SEQ=300><ACK=100><CTL=ACK> <-- ESTABLISHED
5. SYN-SENT --> <SEQ=100><CTL=RST> --> (Abort!!)
6. SYN-SENT CLOSED
7. SYN-SENT --> <SEQ=400><CTL=SYN> -->
注意,接收到
RST
后首先进行验证(RST
的SEQ
必须在窗口内),然后进行重置。
关闭连接
TCP是全双工的,CLOSE
操作却是单工的方式:CLOSE
之后不再发送数据,但仍然可以继续接收数据直到远程TCP关闭。即CLOSE
意味着:我没有要发送的数据了。
对于一方首先关闭连接的情况:
TCP A TCP B
1. ESTABLISHED ESTABLISHED
2. (Close)
FIN-WAIT-1 --> <SEQ=100><ACK=300><CTL=FIN,ACK> --> CLOSE-WAIT
3. FIN-WAIT-2 <-- <SEQ=300><ACK=101><CTL=ACK> <-- CLOSE-WAIT
4. (Close)
TIME-WAIT <-- <SEQ=300><ACK=101><CTL=FIN,ACK> <-- LAST-ACK
5. TIME-WAIT --> <SEQ=101><ACK=301><CTL=ACK> --> CLOSED
6. (2 MSL)
CLOSED
对于双方同时关闭连接的情况:
TCP A TCP B
1. ESTABLISHED ESTABLISHED
2. (Close) (Close)
FIN-WAIT-1 --> <SEQ=100><ACK=300><CTL=FIN,ACK> ... FIN-WAIT-1
<-- <SEQ=300><ACK=100><CTL=FIN,ACK> <--
... <SEQ=100><ACK=300><CTL=FIN,ACK> -->
3. CLOSING --> <SEQ=101><ACK=301><CTL=ACK> ... CLOSING
<-- <SEQ=301><ACK=101><CTL=ACK> <--
... <SEQ=101><ACK=301><CTL=ACK> -->
4. TIME-WAIT TIME-WAIT
(2 MSL) (2 MSL)
CLOSED CLOSED
MSL: Maximum Segment Lifetime, the time a TCP segment can exist in the internetwork system. Arbitrarily defined to be 2 minutes.
参考:RFC-793
本文采用 知识共享署名 4.0 国际许可协议(CC-BY 4.0)进行许可,转载注明来源即可: 读 TCP 协议 RFC-793 | Harttle Land。如有疏漏、谬误、侵权请通过评论或 邮件 指出。
最后
以上就是潇洒猫咪为你收集整理的读 TCP 协议 RFC-793的全部内容,希望文章能够帮你解决读 TCP 协议 RFC-793所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复