TCP协议解析及相关问题

TCP协议是什么:

       TCP是一种传输控制层的协议(TCP,Transmission Control Protocol)是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。也就是要让连接的两端能够读懂相互发送数据的一种保障

TCP协议的主要特点:

1.面向连接的运输层协议,应用程序在使用tcp之前,必须建立tcp连接,在传输完成之后必须释放连接

2.点对点连接,一对一连接

3.tcp提供可靠交付的服务,通过TCP连接传输的数据,无差别,不丢失,不重复,按序到达

4.全双工通信,通信双方可以在任意时刻发送数据,TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据,在发送时,应用程序再把数据传送给TCP缓存后,就可以做自己的事情了,TCP在合适的时候把数据发送出去,在接收时,TCP把收到的数据放入缓存,上层的应用进程在合适的时候读取缓存中的数据

5.面向字节流,TCP中的流指的是流入到进程或者从进程流出的字节序列,虽然应用程序和TCP交互的是大小不等的数据块,但是tcp只保证,发送方和接收方接到的字节流相同。

TCP传送数据的格式:

每一条TCP连接都有两个端点,为套接字(socket)或者插口。端口号拼接ip地址构成套接字(IP地址:端口号)

tcp传送的单元为报文段,报文段=首部(20+4N个字节)+数据

首部前二十个字节为固定的,本文主要介绍以下几个:

                      

     序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生;给字节编上序号后,就给每一个报文段指派一个序号;序列号seq就是这个报文段中的第一个字节的数据编号。

    确认号ack:占4个字节,期待收到对方下一个报文段的第一个数据字节的序号;序列号表示报文段携带数据的第一个字节的编号;而确认号指的是期望接收到下一个字节的编号;因此当前报文段最后一个字节的编号+1即为确认号。

    确认ACK:占1位,仅当ACK=1时,确认号字段才有效。ACK=0时,确认号无效

    同步SYN:连接建立时用于同步序号。当SYN=1,ACK=0时表示:这是一个连接请求报文段。若同意连接,则在响应报文段中使得SYN=1,ACK=1。因此,SYN=1表示这是一个连接请求,或连接接受报文。SYN这个标志位只有在TCP建产连接时才会被置1,握手完成后SYN标志位被置0。

    终止FIN:用来释放一个连接。FIN=1表示:此报文段的发送方的数据已经发送完毕,并要求释放运输连接

  。。。。。。

 ACK、SYN和FIN这些大写的单词表示标志位,其值要么是1,要么是0;ack、seq小写的单词表示序号。

可靠传输的工作原理:

1.停止等待协议

假设A为发送方,B为接收方。

     1)无差别情况:

A发送分组M1,发送之后停止发送,等待B的确认,B收到M1之后会向A发送确认,A在收到B的确认之后,再次发送M2,之后同理。

     2)出现差错:

当A发送分组M1之后,在传输过程中出现了差错,导致B没有接收到M1或丢弃M1,B就不会发送任何确认信息, A在一段时间之后都没有收到确认,会重传M1,称为超时重传(在每次发送完一个分组时候,设置一个超时计时器,如果在超时计时器到期之前收到确认,就会撤销计时器,否则重传M1,M1为已发送分组的副本,在收到相应的确认之后才会清除暂时保留的副本)、

     3)丢失或者确认迟到:

当B收到了A发送的M1之后,B对A发送的确认丢失了,A在超时重传之后,B会得到相同的M1,这个时候B会丢弃重复的分组M1,向A发送确认

2.连续ARQ协议(滑动窗口)

  1. “窗口”对应的是一段可以被发送者发送的字节序列,其连续的范围称之为“窗口”;2. “滑动”则是指这段“允许发送的范围”是可以随着发送的过程而变化的,方式就是按顺序“滑动

3.超时重传

  发送方在规定的时间内没有收到确认就要重传已发送的报文段。

4.基于滑动窗口的流量控制

          TCP头里有一个字段叫Window,又叫Advertised-Window,这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。 滑动窗口是提高TCP传输效率的一种机制。

5.拥塞控制

     tcp拥塞控制的方法  慢开始,拥塞避免,快重传,快恢复

TCP的连接建立:

                            

三次握手:

    1)服务端先创建传输控制块TCB,进入listen状态

     客户端TCP进程主动发出连接请求报文段,首部中SYN=1,报文序列号seq=x的报文段(A),请求建立连接。状态变为SYN-SENT(同步已发送)。

    2)服务器收到对应报文段(A)后,会发出确认报文段(B),SYN和ACK都置为1,确认号ack=x+1(意为对A的确认),同时设定自己的初始序列号seq=y。状态由LISTEN(监听)变为SYN-RCVD(同步收到)。

    3)客户端收到服务器的确认后,还需向服务器发送确认。确认报文段ACK=1,确认号ack=y+1(意为对B的确认),序列号seq=x+1。状态变为ESTABLISHED(已建立连接)。服务器在收到报文段后状态也变为ESTABLISHED。、

为什么客户端需要发送第二次确认:可以防止已失效的请求建立连接报文段又传送到了B,而产生错误

若建立连接只需两次握手,客户端并没有太大的变化,仍然需要获得服务端的应答后才进入ESTABLISHED状态,而服务端在收到连接请求后就进入ESTABLISHED状态。
此时如果网络拥塞,客户端发送的连接请求迟迟到不了服务端,客户端便超时重发请求,如果服务端正确接收并确认应答,双方便开始通信,通信结束后释放连接。
此时,如果那个失效的连接请求抵达了服务端,由于只有两次握手,服务端收到请求就会进入ESTABLISHED状态,等待发送数据或主动发送数据。
但此时的客户端早已进入CLOSED状态,服务端将会一直等待下去,这样浪费服务端连接资源

TCP的连接释放 

                   

四次挥手

     1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1,此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
     2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
     客户端收到服务器的确认请求后,进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
     3)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
     4)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2MSL(2*最长报文段寿命,4分钟)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
        服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

为什么要等待2MSL

       1)为了保证A发送的最后一个ACK报文段能够到达B,客户端发送出最后的ACK报文段有可能会丢失,导致处于LAST-ACK状态的B收不到FIN+ACKb报文段的确认,服务器如果没有收到ACK,将不断重复发送FIN片段。所以客户端不能立即关闭,它必须确认服务器接收到了该ACK。客户端会在发送出ACK之后进入到TIME_WAIT状态。客户端会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

       2)防止已失效的连接请求报文段出现在本连接中,A在发送完最后一个ACK报文段后,经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络消失,这样可以使下一个新的链接中不会出现这种旧的连接请求报文段。 

假设客户端和服务器端已经成功连接,之后客户端主机出现故障

      服务器再也不会收到客户端的数据,不能让服务器白白等待下去,浪费资源,这个时候就用到了保活计时器, 服务器每收到一次客户的数据,就会重新设置保活计时器,通常为两小时,若两个小时都没有收到客户端的数据,服务器就会发送一个探测报文段,以后每隔75分钟发送一次,若连续发送10个探测报文段后,客户端依然无响应,服务器就会关闭本次连接。

原文地址:https://www.cnblogs.com/jiezai/p/11301040.html