TCP 传输控制协议
Transmission Control Protocol
传输控制协议(英语:Transmission Control Protocol,缩写:TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能。用户数据报协议(UDP)是同一层内另一个重要的传输协议。
在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。
应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分割成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元(MTU)的限制)。之后TCP把结果包传给IP层,由它来透过网络将包传送给接收端实体的TCP层。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认信息(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失并进行重传。TCP用一个校验和函数来检验数据是否有错误,在发送和接收时都要计算校验和。
传输层 (Transport Layer)
传输层(英语:Transport Layer)在计算机网络中是互联网协议包与开放系统互连(OSI)网络堆栈中协议的分层结构中的方法的一个概念划分。该层的协议为应用进程提供端到端的通信服务。[1] 它提供面向连接的数据流支持、可靠性、流量控制、多路复用等服务。
互联网与一般性网络的开放系统互连OSI模型的基础,TCP/IP模型的传输层的具体实现和含义(RFC 1122)[2]是不同的。在OSI模型中传输层最常被称作第4层或L4,而TCP/IP中不常给网络层编号。
最著名的TCP/IP传输协议是传输控制协议(TCP), 它的名称借用自整个包的名称。它用于面向连接的传输,而无连接的用户数据报协议(UDP)用于简单消息传输。TCP是更复杂的协议,因为它的状态性设计结合了可靠传输和数据流服务。这个协议组中其他重要协议有数据拥塞控制协议(DCCP)与流控制传输协议(SCTP)。
简介
数据在TCP层称为流(Stream),数据分组称为分段(Segment)。作为比较,数据在IP层称为 Datagram,数据分组称为分片(Fragment)。 UDP 中分组称为 Message。
运作方式
TCP协议的运行可划分为三个阶段:连接创建(connection establishment)、数据传送(data transfer)和连接终止(connection termination)。操作系统将TCP连接抽象为套接字表示的本地端点(local end-point),作为编程接口给程序使用。在TCP连接的生命期内,本地端点要经历一系列的状态改变。
建立通路
TCP用三次握手(或称三路握手,three-way handshake)过程创建一个连接。在连接创建过程中,很多参数要被初始化,例如序号被初始化以保证按序传输和连接的强壮性。
TCP连接的正常创建 一对终端同时初始化一个它们之间的连接是可能的。但通常是由一端(服务器端)打开一个套接字(socket)然后监听来自另一方(客户端)的连接,这就是通常所指的被动打开(passive open)。服务器端被被动打开以后,客户端就能开始创建主动打开(active open)。
服务器端执行了listen函数后,就在服务器上创建起两个队列:
- SYN队列:存放完成了二次握手的结果。 队列长度由listen函数的参数backlog指定。
- ACCEPT队列:存放完成了三次握手的结果。队列长度由listen函数的参数backlog指定。
三次握手协议的过程:
- 客户端(通过执行connect函数)向服务器端发送一个SYN包,请求一个主动打开。该包携带客户端为这个连接请求而设定的随机数A作为消息序列号。
- 服务器端收到一个合法的SYN包后,把该包放入SYN队列中;回送一个SYN/ACK。ACK的确认码应为A+1,SYN/ACK包本身携带一个随机产生的序号B。
- 客户端收到SYN/ACK包后,发送一个ACK包,该包的序号被设定为A+1,而ACK的确认码则为B+1。然后客户端的connect函数成功返回。当服务器端收到这个ACK包的时候,把请求帧从SYN队列中移出,放至ACCEPT队列中;这时accept函数如果处于阻塞状态,可以被唤醒,从ACCEPT队列中取出ACK包,重新创建一个新的用于双向通信的sockfd,并返回。
资源使用
主机收到一个TCP包时,用两端的IP地址与端口号来标识这个TCP包属于哪个session。使用一张表来存储所有的session,表中的每条称作Transmission Control Block(TCB),tcb结构的定义包括连接使用的源端口、目的端口、目的ip、序号、应答序号、对方窗口大小、己方窗口大小、tcp状态、tcp输入/输出队列、应用层输出队列、tcp的重传有关变量等。
数据传输
在TCP的数据传送状态,很多重要的机制保证了TCP的可靠性和强壮性。它们包括:使用序号,对收到的TCP报文段进行排序以及检测重复的数据;使用校验和检测报文段的错误,即无错传输;使用确认和计时器来检测和纠正丢包或延时;流控制(Flow control);拥塞控制(Congestion control);丢失包的重传。
流量控制
流量控制用来避免主机分组发送得过快而使接收方来不及完全收下,一般由接收方通告给发送方进行调控。
TCP使用滑动窗口协议实现流量控制。接收方在“接收窗口”域指出还可接收的字节数量。发送方在没有新的确认包的情况下至多发送“接收窗口”允许的字节数量。接收方可修改“接收窗口”的值。
当接收方宣布接收窗口的值为0,发送方停止进一步发送数据,开始了“保持定时器”(persist timer),以避免因随后的修改接收窗口的数据包丢失使连接的双侧进入死锁,发送方无法发出数据直至收到接收方修改窗口的指示。当“保持定时器”到期时,TCP发送方尝试恢复发送一个小的ZWP包(Zero Window Probe),期待接收方回复一个带着新的接收窗口大小的确认包。一般ZWP包会设置成3次,如果3次过后还是0的话,有的TCP实现就会发RST把链接断了。
如果接收方以很小的增量来处理到来的数据,它会发布一系列小的接收窗口。这被称作愚蠢窗口综合症,因为它在TCP的数据包中发送很少的一些字节,相对于TCP包头是很大的开销。解决这个问题,就要避免对小的window size做出响应,直到有足够大的window size再响应:
- 接收端使用David D Clark算法:如果收到的数据导致window size小于某个值,可以直接ack把window给关闭了,阻止了发送端再发数据。等到接收端处理了一些数据后windows size大于等于了MSS,或者接收端buffer有一半为空,就可以把window打开让发送端再发数据过来。
- 发送端使用Nagle算法来延时处理,条件一:Window Size>=MSS 且 Data Size >=MSS;条件二:等待时间或是超时200ms,这两个条件有一个满足,才会发数据,否则就是在积累数据。Nagle算法默认是打开的,所以对于一些需要小包场景的程序——比如像telnet或ssh这样的交互性程序,需要关闭这个算法。可以在Socket设置TCP_NODELAY选项来关闭这个算法。
拥塞控制
拥塞控制是发送方根据网络的承载情况控制分组的发送量,以获取高性能又能避免拥塞崩溃(congestion collapse,网络性能下降几个数量级)。这在网络流之间产生近似最大最小公平分配。
发送方与接收方根据确认包或者包丢失的情况,以及定时器,估计网络拥塞情况,从而修改数据流的行为,这称为拥塞控制或网络拥塞避免。
TCP的现代实现包含四种相互影响的拥塞控制算法:慢开始、拥塞避免、快速重传、快速恢复。
此外,发送方采取“超时重传”(retransmission timeout,RTO),这是估计出来回通信延迟 (RTT) 以及RTT的方差。
数据包结构
- 序列号(seq,32位长)
- 如果含有同步化旗标(SYN),则此为最初的序列号;第一个资料比特的序列码为本序列号加一。
- 如果没有同步化旗标(SYN),则此为第一个资料比特的序列码。
- 确认号(ack,32位长)—期望收到的数据的开始序列号。也即已经收到的数据的字节长度加1。
- 标志符(9比特长)
- NS—ECN-nonce。ECN显式拥塞通知(Explicit Congestion Notification)是对TCP的扩展,定义于 RFC 3540 (2003)。ECN允许拥塞控制的端对端通知而避免丢包。ECN为一项可选功能,如果底层网络设施支持,则可能被启用ECN的两个端点使用。在ECN成功协商的情况下,ECN感知路由器可以在IP头中设置一个标记来代替丢弃数据包,以标明阻塞即将发生。数据包的接收端回应发送端的表示,降低其传输速率,就如同在往常中检测到包丢失那样。
- CWR—Congestion Window Reduced,定义于 RFC 3168(2001)。
- ECE—ECN-Echo有两种意思,取决于SYN标志的值,定义于 RFC 3168(2001)。
- URG—为1表示高优先级数据包,紧急指针字段有效。
- ACK—为1表示确认号字段有效
- PSH—为1表示是带有PUSH标志的数据,指示接收方应该尽快将这个报文段交给应用层而不用等待缓冲区装满。
- RST—为1表示出现严重差错。可能需要重新创建TCP连接。还可以用于拒绝非法的报文段和拒绝连接请求。
- SYN—为1表示这是连接请求或是连接接受请求,用于创建连接和使顺序号同步
- FIN—为1表示发送方没有数据要传输了,要求释放连接。
- 窗口(WIN,16位长)—表示从确认号开始,本报文的发送方可以接收的字节数,即接收窗口大小。用于流量控制。
- 校验和(Checksum,16位长)—对整个的TCP报文段,包括TCP头部和TCP数据,以16位字进行计算所得。这是一个强制性的字段。