tcp协议详解

什么是TCP协议

tcp(Transmission Control Protocal,传输控制协议)是传输层最重要的协议,它是面向连接、基于字节流,保证报文可靠按序到达的协议。TCP的应用众多,应用层的HTTP、TELNET、TFP等协议都是在TCP的基础上运行的。

tcp是全双工协议,意味着客户端和服务端可以同时发送和接收数据。同时,tcp还是可靠的协议,也就是说不会丢包、不会乱序。同时,TCP还可以根据当前网络的拥塞程度,进行流量控制、拥塞控制。

tcp的实现是通过套接字(socket)来实现的,套接字就是IP地址加上16位的端口号。这样应用层进程就可以根据不同的端口号对tcp进行复用和分用。

TCP如何保证传输的可靠性?

在全双工的工作模式下,接收方的接收缓存和发送方的发送缓存都是有限的,应用程序产生数据过快会导致发送方缓存不足,发送方发送数据过快又会导致接受方接收缓存不足,由此可见,需要一种机制来协调发送方的发送速度和接收方的接收能力相匹配。

停止等待协议

停止等待的意思是,每发送一组数据,就停下来等待,等到收到对方的确认包以后,再次发送。没有差错的情况下,数据包一包一包的进行传输。有差错了,发送方超时没收到确认,则再次发送该包数据。这总机制是自动进行的,因此也叫做自动重传请求ARQ.

ARQ协议的缺点是,一包一包的传输,对网络的利用率过低。优化的协议叫做连续ARQ协议,它的意思是在发送方的发送窗口内,连续的把数据包传输出去,然后再一一进行确认,这样就提高点网络的利用率。发送窗口的大小要取接收窗口和拥塞窗口中的最小值。

TCP报文格式

TCP的报文首部的前20个字节是固定的,后面有4n(n是整数,最大15)个字节是可以增加的选项.

源端口和目的端口: 各两个字节,因此端口的范围是1-65535.

序号: 占4字节,范围[0-2^32-1], 序号会再达到最大值后重置为0

确认号: 期望收到对方下一个报文段的第一个数据的字节的序号。

数据偏移: 占4位,指出TCP报文段的数据起始处距离TCP报文段的数据起始处有多远。

保留: 占6位,保留位以后使用。

下面几个位控制位:

紧急URG: 表明报文中有紧急数据,需要尽快送达。例如,程序中断指令ctrl+c.

确认ACK: 确认报文,ACK=1时有效,TCP建立连接后所有的报文段ACK必须为1

推送PUSH: 希望对方在收到报文后立即做出响应,而不是等缓存填满再发送。

复位RST: 表明TCP连接中断出现严重差错,必须重新连接。(GFW就是这么干的,阻断你请求某些网站的数据。)

同步SYN: 在连接建立时用来同步序号。SYN=1 表示这是要给连接建议请求报文。见后面的三次握手。

终止FIN: 释放连接时使用的标志位

窗口: 两字节,表示的是本报文段一方的接收窗口大小。

校验和: 占2字节,包括首部和数据两部分的校验。

紧急指针: 占2字节,只有在URG为1时才有意义,指出本报文段中紧急数据的字节数(紧急数据结束后就是普通数据),即使窗口为0也可以发送紧急数据。

选项: 长度可变,最长40字节。

可靠传输的实现

以字节为单位的窗口滑动

发送方根据接收方的窗口大小确定发送窗口大小,发送数据后,根据确认的序号,往前滑动窗口。接收方根据自己的缓存大小调整发送方的发送窗口,从而使自己来得及处理接收到的数据。对于不按序到达的数据,通常先进行缓存,等收齐数据再交付上层应用。TCP接收方可以捎带确认以减少传输开销。

超时重传的时间选择

假设一个报文段往返时间RTT,RTTS为多次往返的加权平均值,超时重传的时间要略大于RTTS。只要报文重传了,就不采用加权平均值,这样得出的值相对比较准确。

选择确认ACK

除了累积确认,还可以使用选择确认。就是说接收方接收到的数据为一串不连续的数据包,如果按照之前的确认方式,只能对序号最小的包号进行确认,后续已经接收到的数据包还有可能被重传。选择确认就是在选项中添加一个选项,指明接收到的数据包块,分别进行确认,这样发送方只发送未成功接收的数据包即可。

TCP如何进行流量控制?

TCP的流量控制一般使用滑动窗口来进行流量控制

TCP的拥塞控制?

TCP的拥塞控制有四种方法:慢开始、拥塞避免、快重传和快恢复。

慢开始

慢开始就是维持一个拥塞窗口,从1开始,没有拥塞窗口就扩大一倍,直至增加到发送窗口大小。

拥塞避免

拥塞避免的算法是,让拥塞窗口缓慢的增加,而不是加倍增长。

快重传

快重传,尽快让发送方知道报文丢失。一旦发送方收到3个重复的确认,就知道接收方没有收到某个报文。

快恢复

发送方知道了丢失了某个报文后,不是采用慢开始算法,而是采用快恢复算法,调整发送方窗口为拥塞窗口的1/2,同时执行拥塞避免算法。

TCP的三次握手是怎样的?

  1. 客户端C发起连接请求,SYN=1,seq=x,C进入SYN_SENT状态,
  2. 服务器S收到连接请求后,对报文进行确认 SYN=1,ACK=1,seq=y,ack=x=+1, 进入SYN_RECV状态,
  3. 客户端收到S的确认后,发送确认的确认,ACK=1,seq=x+1,ack=y+1, C进入ESTABLISHED状态。
  4. 服务器收到C的确认报文后,进入ESTABLISHED状态。

为什么建立TCP连接一定需要三次握手?

客户端对服务器的再确认,是为了防止无效的连接报文再次到达服务器端后,建立无效的连接。

如果客户端给服务器的再确认报文丢失了,TCP如何处理?

服务器S如果没有收到确认ACK报文的报文,则会隔3秒、6秒、12秒后再次发送ACK确认报文,如果一段时间内还没收到客户端发来的再确认报文,服务器将关闭这个连接。
当客户端发送数据报文的时候,服务器端会给出RST报文,通知客户端服务器连接已关闭。

TCP的四次分手过程是怎样的?

  1. 客户端C发起连接断开请求,FIN=1,seq=u,然后进入FIN-WAIT-1状态
  2. 服务器S收到C发来的断开请求,发送ACK确认报文,ACK=1,seq=v,ack=u+1, 然后进入CLOSE-WAIT状态
  3. 服务器S发送完剩余的数据,再次发送ACK报文,FIN=1,ACK=1,seq=w,ack=u+1,然后进入LAST-ACK状态
  4. 客户端C收到服务器发送来的ACK报文后,进入TIME-WAIT状态,并发送ACK确认报文,ACK=1,seq=u+1,ack=w+1
  5. 服务器S收到确认报文后,断开连接,进入CLOSE状态,客户端等待2个MSL后断开