TCP协议深入理解
相比于IP协议,TCP协议更加靠近应用层。TCP协议的特点是:面向连接,字节流和可靠传输。通信双方必须先建立连接,这种一对一的连接方式是不能进行多播和广播的。
TCP的传输是可靠的。1)TCP采用发送应答机制,即发送端发送的每个报文都必须得到对方的应答,才能认为传输成功;2)TCP采用超时重传机制,发送端在发出一个TCP报文之后启动定时器,在规定时间内未受到应答,将重发该报文;3)由于TCP报文是包装在IP数据报中,IP数据报到达接收端可能是乱序和重复的,因此TCP协议会对接收的TCP报文进行重排,然后再交付给上层应用。
TCP头部结构
- 16位端口号:告知主机该报文段是来自哪里(源端口)以及传给哪个上层协议或应用程序(目的端口)
- 32位序号:一次TCP通信(从TCP连接建立到 断开)过程中某一个传输方向上的字节流的每个字节的编号,目的是为了对报文排序
- 32位确认号:用作对另一方发送来的 TCP报文段的响应
- 4位头部长度:标识该TCP头部有多少个32bit字 (4字节)
- 6位标志位:URG标志,表示紧急指针是否有效;ACK标志,表示确认号是否有效(确认报文段);PSH标志,提示接收端应用程序应该立即从TCP接收缓冲区中读 走数据,为接收后续数据腾出空间;RST标志,表示要求对方重新建立连接(复位报文段);SYN标志,表示请求建立一个连接(同步报文段);FIN标志,表示通知对方本端要关闭连接了(结束报文段)
- 16位窗口大小:是TCP流量控制的一个手段
- 16位校验和:由发送端填充,接收端对TCP报文段执行CRC算法检验TCP报文段在传输过程中是否损坏,检验内容包括TCP头部部分以及数据部分,保证可靠传输
- 16位紧急指针:是一个正的偏移量,TCP的紧急指针是发送端向接收端发送紧急数据的方法。
TCP头部中的选项
- kind说明选项的类型,有时候选项中只有这一项
- length指定该选项的总长度
- info是选项的具体信息
常见的7种TCP选项:
- kind=0是选项表结束选项。
- kind=1是空操作(nop)选项,没有特殊含义,一般用于将TCP选项的总长度填充为4字节的整数倍。
- kind=2是最大报文段长度选项。TCP连接初始化时,通信双方使用该选项来协商最大报文段长度(MSS)。
- kind=3是窗口扩大因子选项。假设TCP头部中的接收通告窗口大小是N,窗口扩大因子(移位数)是M,那么TCP报文段的实际接收通告窗口大小是N乘2^M。
- kind=4是选择性确认选项(SACK)。SACK技术使TCP模块只重新发送丢失的TCP报文段,不用发送所 有未被确认的TCP报文段。
- kind=5是SACK实际工作的选项,该选项的参数告诉发送方本端已经收到并缓存的不连续的数据块,从而让发送端可以据此检查并重发丢失的数据块。
- kind=8是时间戳选项,该选项提供了较为准确的计算通信双方之间的回路时间的方法,从而为TCP流量控制提供重要信息。
TCP三次握手简单理解:客户端发送含SYN标志的同步报文,给报文一个序号30,告诉服务器“我要连你啦”;服务器收到报文后,它也会发送一个同步报文,序号是89,同时他还会携带对30报文的确认信息31,告诉客户端“我同意你的连接啦,我也收到你的30号信息啦”;最后,客户端又会礼貌的回复服务器“谢谢啦,我看到你给我发的89号报文啦”,这段确认报文序号是90。
TCP四次握手简单理解:客户端想结束连接,给服务器发送含有FIN的结束报文,序号为19,告诉服务器“我要离开啦,你关上门吧”;服务器收到消息之后,告诉客户端“知道啦,我收到了你的消息啦”,报文序号为20;然后客户端马上又发送含有FIN的结束报文,告诉客户端“我关门啦,你走吧”,报文序号为08;客户端接连收到两个报文,一个是他知道我要走了,一个是他关门了,然后客户端最后跟他说了“再见”,报文序号为09。
TCP状态转移
- 服务器通过listen系统调用进入LISTEN状态,被动等待客户端连接,被动打开,服务器一旦监听到某个连接请求,将该连接放入内核等待队列中,并向客户端发送带SYN标志的确认报文段。此时该连接处于SYN_RCVD 态。如果服务器成功地接收到客户端发送回的确认报文段,则该连接转 移到ESTABLISHED状态。ESTABLISHED状态是连接双方能够进行双 向数据传输的状态。
- 当客户端主动关闭连接时,服务器通过返回确认报文段使连接进入CLOSE_WAIT状态,服务器检测到客户端关闭连接后,也会立即给客户端发 送一个结束报文段来关闭连接。这将使连接转移到LAST_ACK状态,以等待客户端对结束报文段的最后一次确认。一旦确认完成,连接就彻底关闭了。
- 客户端通过connect系统调用主动与服务器建立连接,connect系统调用首先给服务器发送一个同步报文段,使连接转移到 SYN_SENT状态。connect系统调用可能因为如下两个原因失败返回:1)如果connect连接的目标端口不存在,或者该端口仍被处于TIME_WAIT状态的连接所占用,则服务器将给客户端发送一个复位报文段,connect调用失败;2)如果目标端口存在,但connect在超时时间内未收到服务器的确认报文段,则connect调用失败。connect调用失败将使连接立即返回到初始的CLOSED状态,connect调用成功返回,连接转移至ESTABLISHED状态。
- 当客户端执行主动关闭时,它将向服务器发送一个结束报文段,同时连接进入FIN_WAIT_1状态。若此时客户端收到服务器专门用于确认目的的确认报文段,则连接转移至 FIN_WAIT_2状态。当客户端处于FIN_WAIT_2状态时,服务器处于 CLOSE_WAIT状态,这一对状态是可能发生半关闭的状态。此时如果服务器也关闭连接(发送结束报文段),则客户端将给予确认并进入 TIME_WAIT状态。
- 客户端从FIN_WAIT_1状态直接进入TIME_WAIT状态的一条线路(不经过FIN_WAIT_2状态),前提是处于FIN_WAIT_1 状态的服务器直接收到带确认信息的结束报文段(而不是先收到确认报文段,再收到结束报文段)。
TIME_WAIT状态
当客户端收到服务器的结束报文之后没有进入closed状态,就会转移到TIME_WAIT状态,在这个状态下,客户端连接要等待一段长为2MSL的时间才能关闭。MSL是TCP报文段在网络中的最大生存时间,TIME_WAIT状态存在的原因:
- 可靠地终止TCP连接。例如服务器的结束报文丢失,服务器将重发结束报文,因此客户端需要停留在某个状态,以确保可靠的终止连接。
- 保证让迟来的TCP报文段有足够的时间被识别并丢弃。
复位报文段
在某些特殊条件下,TCP连接的一端会向另一端发送携带RST标志 的报文段,即复位报文段,以通知对方关闭连接或重新建立连接。产生复位报文的3种情况:
- 访问不存在的端口:当客户端程序访问一个不存在的端口时,目标主机将给它发送一个复位报文段,收到复位报文段的一端应该关闭连接或者重新连接,而不能回应这个复位报文段。
- 异常终止连接:TCP提供了异常终止一个连接的方法,即给对方发送一个复位报文段。一旦发送了复位报文段,发送端所有排队等待发送的数据都将被丢弃。
- 处理半打开连接:当通信双方的某一端关闭或异常终止了连接,但是对方没有收到结束报文,则会一直维持原来的连接,这种状态称为半打开状态。当往半打开状态的客户端或服务器写入数据时,对方会回应一个复位报文。
TCP数据流
TCP报文段所携带的应用程序数据按照长度分为两种:交互数据和成块数据
交互数据:仅包含很少的字节。使用交互数据的应用程序对实时性要求高,比如telnet、ssh等;
成块数据:长度通常为TCP报文段允许的最大数据长度。使用成块数据的应用程序对传输效率要求高,比如ftp;
TCP数据流的控制
超时重传:TCP服务必须能够重传超时时间内未收到确认的TCP报文段,为此,TCP模块为每个TCP报文段都维护一个重传定时器,该定时器在TCP报文段第一次被发送时启动。如果超时时间内未收到接收方的应答,TCP模块将重传TCP报文段并重置定时器。
拥塞控制:TCP模块还有一个重要的任务,就是提高网络利用率,降低丢包率,并保证网络资源对每条数据流的公平性。这就是所谓的拥塞控制。计算机网络的时候有详细学过,这里不做过多赘述,直接放一个经典图吧: