传输控制协议(英语:Transmission Control Protocol, TCP)
一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,用户数据报协议(UDP)是同一层内另一个重要的传输协议。
在因特网协议族(Internet protocolsuite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像渠道一样的连接,但是IP层不提供这样的流机制, 而是提供不可靠的包交换。
应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元(MTU)的限制)。之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体的TCP层。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。
运作方式
TCP连接包括三个状态:连接创建、数据传送和连接终止。操作系统将 TCP 连接抽象为套接字的编程接口给程序使用,并且要经历一系列的状态改变。
连接创建
TCP用三路握手(three-way handshake)过程创建一个连接。在连接创建过程中,很多参数要被初始化,例如序号被初始化以保证按序传输和连接的强壮性。
一对终端同时初始化一个它们之间的连接是可能的。但通常是由一端打开一个套接字(socket)然后监听来自另一方的连接,这就是通常所指的被动打开(passive open)。 服务器端被被动打开以后,用户端就能开始创建主动打开(active open)。如图:
![](https://www.#.com/imgs/2/8/8/4/19/d560eeeba9e07ec9e7abf73325c02307.jpe)
具体过程:
1、客户端通过向服务器端发送一个SYN来创建一个主动打开,作为三路握手的一部分。客户端把这段连接的序号设定为随机数 A。
2、服务器端应当为一个合法的SYN回送一个SYN/ACK。ACK 的确认码应为 A+1,SYN/ACK 包本身又有一个随机序号 B。
3、最后,客户端再发送一个ACK。当服务端受到这个ACK的时候,就完成了三路握手,并进入了连接创建状态。此时包序号被设定为收到的确认号 A+1,而响应则为 B+1。
数据传输:
在TCP的数据传送状态,很多重要的机制保证了TCP的可靠性和强壮性。它们包括:使用序号,对收到的TCP报文段进行排序以及检测重复的数据;使用校验和来检测报文段的错误;使用确认和计时器来检测和纠正丢包或延时。
序列号和确认:
在TCP的连接创建状态,两个主机的TCP层间要交换初始序号(ISN:initial sequence number)。 这些序号用于标识字节流中的数据,并且还是对应用层的数据字节进行记数的整数。通常在每个TCP报文段中都有一对序号和确认号。TCP报文发送者认为自己的字节编号为序号,而认为接收者的字节编号为确认号。TCP报文的接收者为了确保可靠性,在接收到一定数量的连续字节流后才发送确认。这是对TCP的一种扩展,通常称为选择确认(Selective Acknowledgement)。 选择确认使得TCP接收者可以对乱序到达的数据块进行确认。每一个字节传输过后,ISN号都会递增1。
通过使用序号和确认号,TCP层可以把收到的报文段中的字节按正确的顺序交付给应用层。序号是32位的无符号数,在它增大到232-1时,便会回绕到0。对于ISN的选择是TCP中关键的一个操作,它可以确保强壮性和安全性。
数据传输举例:
1、发送方首先发送第一个包含序列号为1(可变化)和1460字节数据的TCP报文段给接收方。接收方以一个没有数据的TCP报文段来回复(只含报头),用确认号1461来表示已完全收到并请求下一个报文段。
2、发送方然后发送第二个包含序列号为1461和1460字节数据的TCP报文段给接收方。正常情况下,接收方以一个没有数据的TCP报文段来回复,用确认号2921(1461+1460)来表示已完全收到并请求下一个报文段。发送接收这样继续下去。
3、然而当这些数据包都是相连的情况下,接收方没有必要每一次都回应。比如,他收到第1到5条TCP报文段,只需回应第五条就行了。在例子中第3条TCP报文段被丢失了,所以尽管他收到了第4和5条,然而他只能回应第2条。
4、发送方在发送了第三条以后,没能收到回应,因此当时钟(timer)过时(expire)时,他重发第三条。(每次发送者发送一条TCP报文段后,都会再次启动一次时钟:RTT)。
5、这次第三条被成功接收,接收方可以直接确认第5条,因为4,5两条已收到。
![](https://www.#.com/imgs/2/2/7/6/38/8c082c6a7675093554cb2aa3a7a68e43.jpe)
校验和:
TCP的16位的校验和(checksum)的计算和检验过程如下:发送者将TCP报文段的头部和数据部分的和计算出来,再对其求反码(一的补数),就得到了校验和,然后将结果装入报文中传输。(这里用反码和的原因是这种方法的循环进位使校验和可以在16位、32位、64位等情况下的计算结果再叠加后相同)接收者在收到报文后再按相同的算法计算一次校验和。这里使用的反码使得接收者不用再将校验和字段保存起来后清零,而可以直接将报文段连同校验加总。如果计算结果是全部为一,那么就表示了报文的完整性和正确性。
注意:TCP校验和也包括了96位的伪头部,其中有源地址、目的地址、协议以及TCP的长度。这可以避免报文被错误地路由。
按现在的标准,TCP的校验和是一个比较脆弱的校验。出错概率高的数据链路层需要更高的能力来探测和纠正连接错误。TCP如果是在今天设计的,它很可能有一个32位的CRC校验来纠错,而不是使用校验和。但是通过在第二层使用通常的CRC校验或更完全一点的校验可以部分地弥补这种脆弱的校验。第二层是在TCP层和IP层之下的,比如PPP或以太网,它们使用了这些校验。但是这也并不意味着TCP的16位校验和是冗余的,对于因特网传输的观察,表明在受CRC校验保护的各跳之间,软件和硬件的错误通常也会在报文中引入错误,而端到端的TCP校验能够捕捉到很多的这种错误。这就是应用中的端到端原则。
TCP数据传输不同于UDP之处:
有序数据传输
重发丢失的数据包
舍弃重复的数据包
无错误数据传输
阻塞/流量控制
面向连接(确认有创建三方交握,连接已创建才作传输。)
端口
TCP使用了端口号(Port number)的概念来标识发送方和接收方的应用层。对每个TCP连接的一端都有一个相关的16位的无符号端口号分配给它们。端口被分为三类:众所周知的、注册的和动态/私有的。众所周知的端口号是由因特网赋号管理局(IANA)来分配的,并且通常被用于系统一级或根进程。众所周知的应用程序作为服务器程序来运行,并被动地侦听经常使用这些端口的连接。例如:FTP、TELNET、SMTP、HTTP等。注册的端口号通常被用来作为终端用户连接服务器时短暂地使用的源端口号,但它们也可以用来标识已被第三方注册了的、被命名的服务。动态/私有的端口号在任何特定的TCP连接外不具有任何意义。可能的、被正式承认的端口号有65535个。
数据包结构:
![](https://www.#.com/go/)
![](https://www.#.com/go/)
偏移 |
位 0–3 |
4–7 |
8–15 |
16–31 |
0 |
来源连接端口 |
目的连接端口 |
32 |
序列号码 |
64 |
确认号码 |
96 |
报头长度 |
保留 |
标志符 |
窗口大小 |
128 |
校验和 |
紧急指针 |
160 |
选项字段 |
160/192+ |
数据 |
来源连接端口(16位长)-辨识发送连接端口
目的连接端口(16位长)-辨识接收连接端口
序列号(seq,32位长)
确认号(ack,32位长) —期望收到的数据的开始序列号。也即已经收到的数据的字节长度加1。
如果含有同步化旗标(SYN),则此为最初的序列号;第一个数据比特的序列码为本序列号加一。
如果没有同步化旗标(SYN),则此为第一个数据比特的序列码。
报头长度 —以4字节为单位计算出的数据段开始地址的偏移值。
保留 —须置0
标志符
URG —为1表示高优先级数据包,紧急指针字段有效。
ACK —为1表示确认号字段有效
PSH —为1表示是带有 PUSH 标志的数据,指示接收方应该尽快将这个报文段交给应用层而不用等待缓冲区装满。
RST —为1表示出现严重差错。可能需要重现创建TCP连接。还可以用于拒绝非法的报文段和拒绝连接请求。
SYN —为1表示这是连接请求或是连接接受请求,用于创建连接和使顺序号同步
FIN —为1表示发送方没有数据要传输了,要求释放连接。
窗口(WIN) —表示从确认号开始,本报文的源方可以接收的字节数,即源方接收窗口大小。用于流量控制。
校验和 —对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字进行计算所得。这是一个强制性的字段。
紧急指针 —本报文段中的紧急数据的最后一个字节的序号。
选项字段 —最多40字节。每个选项的开始是1字节的kind字段,说明选项的类型。
0:选项表结束(1字节)
1:无操作(1字节)用于选项字段之间的字边界对齐。
2:最大报文段长度(4字节,Maximum Segment Size,MSS)通常在创建连接而设置SYN标志的数据包中指明这个选项,指明本端所能接收的最大长度的报文段。通常将MSS设置为(MTU-40)字节,携带TCP报文段的IP数据报的长度就不会超过MTU,从而避免本机发生IP分片。只能出现在同步报文段中,否则将被忽略。
3:窗口扩大因子(4字节,wscale),取值0-14。用来把TCP的窗口的值左移的位数。只能出现在同步报文段中,否则将被忽略。这是因为现在的TCP接收数据缓冲区(接收窗口)的长度通常大于65535字节。
4:sackOK —发送端支持并同意使用SACK选项。
5:SACK实际工作的选项。
8:时间戳(10字节,TCP Timestamps Option,TSopt)
发送端的时间戳(Timestamp Value field,TSval,4字节)
时间戳回显应答(Timestamp Echo Reply field,TSecr,4字节)