TCP/IP协议是网络七层协议中最重要的两个协议,一个负责传输层的数据传输,一个负责网络层的数据传输。它的重要程度之高导致有时候七层协议直接称为TCP/IP协议。所以对TCP/IP协议的了解将决定了在服务器端开发、调试中是否能快速定位到问题,程序优化方向是否正确。在这篇文章中主要是针对TCP的协议格式与链接、断开过程进行简单分析。
TCP(Transimission Control Protocol)负责传输层的数据传输,并保证数据的完整性与有序性,是面向链接、字节流传输(UDP面向无连接、数据包传输)。它是在协议栈的第四层传输层使用到的协议,通过IP协议传输。因为在IP网络层是点对点,随机选择路由进行跳转转发的,没有办法保证任何一个IP数据包都可以正常准时到达对端。因此在IP层是无法保证数据的完整性,只能依靠更高层的协议保证。TCP是如何保证数据的有序与完整性的那,那需要对TCP协议进行介绍。
首先对TCP的头部进行一个简单的介绍说明。
通过上图可以看到,一般情况下,TCP的头部是20个字节,最后一个四个字节记录检验和与紧急指针。那么TCP的头部是如何解决了数据的有序性与完整性的那?在回答问题之前还要对有序性再多说一句。这里的有序性并不是指的一端发送数据,另一端是有序接收到。不是指发送端先发包A,又发送了包B,而接收端就一定是先接收到A,再接受到B。这里的有序性可以理解成数据最终有序性。因为网络的问题,无论什么协议都不可能保证数据有序接收。因为TCP数据流会以往网络层的IP包来传输,而IP是随机选择路由的(其实也不是随机),不可能保证先后发送的IP报可以先后被对端接收到。虽然TCP接受端不能有序接受到数据,但是它可以有其他机制来保证数据最终有序。下面就对头部简单介绍来分析它是如何保证有序和完整性的。
一个TCP报文不可能很小,因为如果很小那么我们可以计算一下在一次TCP传输中传输非有效字节是多少。这里的非有效字节是指非发送端直接想要发送的数据,而是每一层协议中额外添加的头部,数据检验和,各种标识等字段。我们从传输层开始算起,TCP头部至少20字节,IP头部至少20字节,数据链路层X字节(要看具体协议),我们可以看到非有效数据是肯定要大于40字节的。如果你传输的数据很少,还么有各层协议栈的头部数据大,那么网络资源就很大一部分浪费掉。
但是又不能很大,这里主要有两个原因。
第一个因为无论上层数据是采用什么协议,最终都会用底层的物理层进行传输。在这里简单介绍一下以太网的传输机制。由于以太网传输受物理设备方面的限制,每个以太网帧都有最小的大小64B,最大不能超过1500B。对于不在这两个区间的的以太网帧我们都可以视之为无效的数据帧,转发设备会丢弃这些数据帧。对于这两个区间分别减去帧头则是可以传输的上次数据的大小。MAC目的地址6B,MAC源地址6B,Type域2B和帧尾CRC校验部分4B总共18B,所以可以有效传输数据为1500B。当TCP报文过大的时候,就会导致很多分段,不仅没有增加传输效率而且还会降低。
第二个原因其实是对第一个原因的解释,那就是为什么底层传输不把包设置的很大,这样就不用分片了啊。原因主要是当一个包很大的时候,网络延时会比较大,不可控事件更容易发生;而且包越大,数据越容易有出错的bit出现,导致接受到的数据无效而丢弃。
通过上图可以看出典型TCP连接的三次握手。
第一步:由一端发出连接请求,发出同步序号syn;
和TCP连接不同的是,TCP断开采用了四次握手的机制。因为对于发送端和接收端来说,谁都可以单独发出断开的请求。因此整个连接的彻底断开需要每个端都发送一对断开请求和对请求的确认。这就会出现断开过程需要四次握手机制。
下面就对图进行介绍,其中有几个关键状态(注意,所有状体都是针对上图说明的;当服务端提出断开的时候,状态正好全部对调):
1:FIN_WAIT_1,客户端首先发送FIN,告诉服务端请求断开,等待服务端确认。这个时刻一般就是客户端发送完数据,已经没有东西发送。
2:FIN_WAIT_2,客户端接收到服务端对FIN的确认ACK,客户端进入当前状态。在这种状态下,客户端只可以接受数据,不可发送数据。
3:CLOSE_WAIT,当服务端接受到客户端发送的FIN请求的时候,发送ACK给客户端,进入该状态。
4:LAST_ACK,服务端发送完数据,处理结束,这个时候向客户端发送FIN请求,请求自己端断开连接。
5:TIME_WAIT,客户端接收到服务端发送FIN请求,发送ACK,进入此状态。在这个状态,无论是客户端还是服务端都不能发送和接受数据。TIME_WAIT状态只有谁先提出断开,谁才会进入这个状态。
在TIME_WAIT一段时间以后,进入真正的CLOSED状态,等待时间是为了防止之前发送的FIN或者ACK被下一个连接接受到,而导致误断开的情况。
IP:http://www.infocellar.com/networks/ip/ip-packet.htm
TCP wiki:TCP wiki