一:TCP协议简介
TCP为传输控制协议(TransmissionControl Protocol)。TCP是一个面向连接的协议,为用户提供可靠的全双工字节流。TCP套接字是一种流套接字。
面向连接意味着两个使用TCP的用应在彼此交换数据之前必须先建立连接,双方都应该在内核中分配资源,当连接断开时都应该清理资源。TCP协议通过数据确认、超时重传、流量控制来保证可靠性。全双工意味在一个给定的连接上应用可以在任何时刻在进出两个方向上即发送数据又接收数据。着基于流的数据没有边界(长度)的限制,它源源不断的从一端发往另一端。
TCP首部:
TCP首部信息出现在每个tcp报文中,包含连接的源端口、目的端口、序号、标志位、滑动窗口等信息。源端口和目的端口用于寻找收发端的应用进程,这两个值加上IP首部的的源IP和目的IP地址可以唯一确认一个TCP连接。序号用来表示从TCP发端向TCP收端发送的数据字节流,表示在这个报文段中的第一个数据字节。确认位为TCP收端对TCP发端报文段的响应,其取值为收到的TCP报文段序号加1,代表发送确认的一端所希望收到的下一个序号。头部长度标识该TCP首部有多少个32bit字(4字节)。标识位设置为1标识对应的功能有效,可多个同设置为1。窗口大小告知对方当前自己的缓存区最多还能容纳多少字节,这样发送方可以用来控制发送数据段是速度,是TCP流量控制的一种手段。校验和为对TCP报文段(TCP首部和数据)执行CRC算法的结果,接收端用来校验TCP报文在传输过程中是否损坏。
二:TCP连接的建立和与终止
TCP是一个面向连接的协议,无论哪一方向另一方发送数据之前 都必须先在双方之间建立连接,数据交互完成后需要关闭连接。下面分别介绍一下TCP的连接和终止都做了那些事情。
连接的建立(三次握手):
建立一个连接需要三次握手,如图所示:
1:客户端发送一个SYN(包头中的SYN标志位设置为1,后续的FIN、ACK同理)段指明客户端打算连接服务器的端口,以及初始序号 (ISN 图中J,当前报的序号为ISN), ISN的值随时间而变化,这样可以保证每个连接都有不同的ISN。这样选择的目的在于防止在网络中被延迟的分组在以后又被传送,而导致某个连接的一方对它做错误的解释。
2:服务器发回包含服务器的初始序号(ISN 图中K)的SYN报文作为应答。同时将确认序号设置为客户端的ISN加1(图中 J+1, SYN报文也需要占用序号,所以下一个序号为J+1)对客户端的SYN报文进行确认(即ACK)。
3:客户端必须将确认号设置为服务器的ISN加1(图中 K+1)以对服务器的SYN报文进行确认(即ACK)。
连接的终止(四次握手):
终止一个连接要经过四次握手,这是由于TCP的半关闭造成的。既然一个TCP连接是全双工(即数据能在两个方向上同时传递),那么每个方向都必须单独的进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。当一端收到一个FIN,它必须通知应用层另一端已经终止了那个方向的数据传送。连接终止过程如图所示:
1:首先客户端(也可以服务端先关闭)想服务端发送一个FIN小心,表示数据发送完毕,需要终止连接。同时客户端将不再发送任何数据了,但是可以接受对方的发过来的数据。
2:服务器收到客户端发过来的FIN消息后向客户端发送一个确认(ACK)。 FIN消息的接受也作为一个文件结束符传递给前端应用层进程(放在该应用进程已排队等候的任何其他数据之后)。到了步,该TCP连接进入半关闭状态。
3:一段时间之后,服务端应用程序收到客户端关闭的消息(2中的文件结束符)而关闭该连接,导致服务端向发送一个FIN报文。
4:客户端在收到服务端发送过来的FIN消息后返回一个ACK,确认这个FIN。
三:TCP连接的状态迁移
TCP连接的任意一端在任意一时刻都处于某种状态。下图中描述TCP连接过程中各个阶段的状态及各个状态的转移流程。
说明:图中粗虚线表示典型的服务端连接的状态转移。粗实线表示典型的客户端连接的状态的状态转移。CLOSED是一个假想的起始点,并不是一个实际状态。
ESTABLISHED状态:两个导致进入ESTABLISHED状态的变迁对应打开一个连接,而两个导致从ESTABLISHED状态离开的变迁对应关闭一个连接。
CLOSE_WAIT状态:该状态是在收到主动关闭端FIN消息并返回ACK后进入的状态,在该状态中,被动关闭一段将收包队列中的数据处理完之后并加盖回包发送完才会发送FIN消息。
TIME_WAIT状态:该状态也称为2MSL等待状态, 每个TCP实现必须必须选择一个报文报文段最大生存时间MSL(Maximum Segment Lifetime)。它是任何报文被丢弃前在网络内的最长时间。该状态存在的意义在于:
1:可靠地终止TCP连接:
在进行关闭连接四路握手协议时,最后的ACK是由主动关闭端发出的,如果这个最终的ACK丢失,被动关闭端将重发最终的FIN,因此主动关闭端必须维护状态信息允许它重发最终的ACK。如果不维持这个状态信息,那么客户端将响应RST分节,服务器将此分节解释成一个错误。
2:保证让迟来的TCP报文段有足够的的时间被识别并丢弃:
TCP分节可能由于路由器异常而“迷途”,在迷途期间,TCP发送端可能因确认超时而重发这个分节,迷途的分节在路由器修复后也会被送到最终目的地。在关闭一个TCP连接后,马上又重新建立起一个相同的IP地址和端口之间的TCP连接,后一个连接被称为前一个连接的化身,那么有可能出现这种情况,前一个连接的迷途重复分组在前一个连接终止后出现,从而被误解成从属于新的化身。为了避免这个情况,TCP不允许处于TIME_WAIT状态的连接启动一个新的化身,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个TCP连接的时候,来自连接先前化身的重复分组已经在网络中消逝。
参考文档:
《TCP/IP 详解》卷一
《UNIX 网络编程》卷一
《LINX高性能服务器编程》