为了准确无误将数据送达目标处,TCP协议采用了三次握手策略。
建立一个TCP连接需要”三次握手“,缺一不可:
- **一次握手:**客户端发送带有
SYN(SEQ=x)
标志的数据报 -> 服务端,然后客户端进入SYN_SEND
状态,等待服务器的确认。 - 二次握手:服务器端发送带有
SYN+ACK(SEQ=y,ACK=x+1)
标志的数据报 -> 客户端,然后服务端进入SYN_RECV
状态。 - **三次握手:**客户端发送带有
ACK(ACK = y+1)
标志的数据报 -> 服务端,然后客户端和服务端都进入ESTABLISHED
状态,完成TCP三次握手。
三次握手的目的是简历可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。
- 第一次握手:
Client
什么都不能确认;Server
确认了对方发送正常,自己接受正常。 - 第二次握手:
Client
确认了:自己发送、接受正常,对方发送、接受正常;Server
确认了:对方发送正常,自己接受正常 - 第三次握手:
Client
确认了:自己发送、接受正常,对方发送、接受正常;Server
确认了:自己发送、接受正常,对方发送、接受正常。
服务端传回发送端所发送的ACK是为了告诉客户端:“我接收到的信息确实就是你所发送的信号了”,这表明从客户端到服务端的通信是正常的。回传SYN则是为了建立并确认从服务端到客户端的通信。
SYN同步序列编号(Synchronize Sequence Numbers)是TCP/IP建立连接时使用的握手信号。在客户机和服务器之间建立正常的TCP网络连接时,客户机首先发出一个SYN消息,服务器使用SYN-ACK应答表示接收到了这个消息,最后客户机再以ACK(Acknowledgement)消息响应。这样再客户机和服务器之间才能建立起可靠的TCP连接,数据才可以在客户机和服务器之间传递。
断开一个TCP连接需要“四次挥手”,缺一不可。
- **第一次回收:**客户端发送一个
FIN(SEQ=X)
标志的数据报 -> 服务端,用来关闭客户端到服务器的数据传送。然后,客户端进入FIN-WAIT-1
状态。 - **第二次挥手:**服务器收到这个
FIN(SEQ=X)
标志的数据报,他发送一个ACK(SEQ=X+1)
标志的数据报 -> 客户端。然后,此时服务端进入CLOSE-WAIT
状态,客户端进入FIN-WAIT-2
状态。 - **第三次挥手:**服务端关闭与客户端的连接并发送一个
FIN(SEQ=y)
标志的数据报 -> 客户端请求关闭连接,然后,服务端进入LAST-ACK
状态。 - **第四次挥手:**客户端发送
ACK(SEQ=y+1)
标志的数据报 -> 服务端并且进入TIME-WAIT
状态,服务端在收到ACK(SEQ=y+1)
标志的数据报后进入CLOSE
状态。此时,如果客户端等待2MSL
后依然没有收到回复,就证明服务端已正常关闭,随后,客户端也可以关闭连接了。
TCP是全双工通信,可以双向传输数据。任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送时,则发出连接释放通知,对方确认后就完全关闭了TCP连接。
因为服务器收到客户端断开连接的请求时,可能还有一些数据没有发完,这时先回复ACK,表示接受到了断开连接的请求。等到数据发完之后再发FIN,断开服务器到客户端的数据传送。
第四次挥手时,客户端发送给服务器的ACK有可能丢失,如果服务端因为某些原因而没有收到ACK的话,服务端就会重发FIN,如果客户端在2MSL的时间内收到了FIN,就会重新发送ACK并再次等待2MSL,防止Server没有收到ACK而不断重发FIN。
MSL(Maximum Segment Lifetime):一个片段在网络中最大的存活时间,2MSL就是要给发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
- **基于数据块传输:**应用数据被分割成TCP认为最适合发送的数据块,再传输给网络层,数据块被称为报文段或段。
- **对失序数据包重新排序以及去重:**TCP为了保证不发生丢包,就给每个包一个序列号,有了序列号能够接收到的数据根据序列号排序,并且去掉重复序列号的数据就可以实现数据包去重。
- 校验和:TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和差错,TCP将丢弃这个报文段和不确认收到此报文段。
- **超时重传:**当发送方发送数据之后,它启动一个定时器,等待目的端确认收到这个报文段。接收端实体对已收到的包发回一个相应的确认信息(ACK)。如果发送端实体在合理的往返时延(RTT)内未收到确认消息,那么对应的数据包就假设为已丢失并进行重传。
- **流量控制:**TCP连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP使用的流量控制协议是可变大小的滑动窗口协议(TCP利用滑动窗口实现流量控制)。
- **拥塞控制:**当网络拥塞时,减少数据的发送。
**TCP利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。**接收方发送的确认报文中的窗口字段可以用来控制i发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为0,则发送方不能发送数据。
**为什么需要流量控制?这是因为双方在通信的时候,发送方的速率与接收方的速率不一定相等,如果发送方的发送速率太快,会导致接收方处理不过来。如果接收方处理不过来的话,就只能把处理不过来的数据存在接收缓冲区(Receiving Buffers)**里(失序的数据包也会被存放在缓存区)。如果缓存区满了发送方还在狂发数据,接收方只能把收到的数据报丢掉。出现丢包问题的同时又疯狂浪费资源。因此,我们需要控制发送方的发送速率,让接收方与发送方处于一种动态平衡才好。
这里需要注意:
- 发送端不等同于客户端
- 接收端不等同于服务端
TCP为全双工(Full-Duplex,FDX)通信,双方可以进行双向通信,客户端和服务端极可能是发送端有可能是接收端。因此,两端各有一个发送缓冲区和接收缓冲区,两端各自维护一个发送窗口和一个接收窗口。接收窗口大小取决于应用、系统、硬件的限制(TCP传输速率不能大于应用的数据处理速率)。通信双方的发送窗口和接受床的要求相同。
TCP发送窗口可以划分成四个部分:
- 已经发送并且确认的TCP段(已经发送并确认)
- 已经发送但是没有确认的TCP段(已经发送未确认)
- 未发送但是接收方准备接收的TCP段(可以发送)
- 未发送并且接收方也并未准备接收的TCP段(不可发送)
SND.WND
:发送窗口SND.UND
:Send Unacknowledged
指针,指向发送窗口的第一个字节SND.NXT``Send Next
指针,指向可用窗口的第一个字节
**可用窗口大小 = **SND.UNA + SND.WND - SND.NXT
。
TCP接收窗口可以划分成三个部分:
- 已经接收并且已经确认的TCP段(已经接收并确认)
- 等待接收且允许发送方发送的TCP段(可以接收未确认)
- 不可接受且不允许发送方发送TCP段(不可接收)
TCP接收窗口结构图示:
接收窗口的大小是根据接收端处理数据的速度动态调整的。如果接收端读取数据块,接收窗口可能会扩大。否则,他可能会缩小。
另外,这里的滑动窗口大小只是为了演示使用,实际窗口大小通常会远远大于这个值。
在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。
为了进行拥塞控制,TCP发送方要维持一个**拥塞窗口(cwnd)的状态变量。拥塞控制窗口的大小取决于网络的拥塞程度,并且动态变化。发送方让自己的发送窗口取为拥塞窗口和接收方的接收窗口中较小的一个。
TCP的拥塞控制采用了四种算法:即慢开始、拥塞避免、快重传和快恢复。**在网络层中也可以使路由器采用适当的分组丢弃策略(如主动队列管理AQM),以减少网络拥塞的发生。
- **慢开始:**慢开始算法的思路是当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么可能引起网络阻塞,因为现在还不知道网络的负荷情况。经验表明,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是由小到大逐渐增加拥塞窗口数值。
cwnd
初始值为1,没经过一个传播轮次,cwnd
加倍。 - **拥塞避免:**拥塞避免算法的思路是让拥塞窗口
cwnd
缓慢增大,即没经过一个往返时间RTT
就把发送方的cwnd
加一。 - **快重传和快恢复:**在
TCP/IP
中,快重传和快恢复(FRR)是一种拥塞控制算法,它能快速恢复丢失的数据报。没有FRR
,如果数据包丢失了,TCP将会使用定时器来要求传输暂停。在暂停的这段时间内,没有新的或复制的数据包被发送。有了FRR
,如果接收机接收到一个不按顺序的数据段,它会立即给发送机发送一个重复确认。如果发送机接收到三个重复确认,它会假定确认件支出的数据段丢失了,并立即重传这些丢失的数据段。有了FRR
,就不会因为重传时要求的暂停被耽误。当有单独的数据包丢失时,快重传和快恢复能最有效的工作,当多个数据信息报在某一段很短的时间内丢失时,它则不能很有效的工作。
**自动重传请求(Automatic Repeat-reQuest,ARQ)**是OSI
模型中数据链路层和传输层的错误纠正协议之一。它通过使用确认和超时这两个机制,在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送一段时间之内没有收到确认信息(Acknowledgments,就是我们产说的ACK),他通常会重新发送,直到收到确认或者重试超过一定的次数。
ARQ包括停止等待ARQ协议和连续ARQ协议。
停止等待协议是为了实现可靠传输的,它的基本原理就是没法玩一个分组就停止发送,等待对方确认(回复ACK)。如果过了一段时间(超过时间后),还是没有收到ACK确认,就说明发送失败,需要重新发送,直到收到确认后再发下一个分组。
在停止等待协议中,若接收方收到重复分组,就丢弃该分组,但同时还要发送确认。
1)无差错情况:
发送方发送分组,接收方在规定时间内收到,并且回复确认,发送方再次发送。
2)出现差错情况(超时重传):
停止等待协议中超时重传是指只要超过一段时间仍然没有收到确认,就重传前面发送过的分组(认为刚才发送过的分组丢失了)。因此每发送完一个分组需要设置一个超时计时器,其重传时间应比数据在分组传输的平均往返时间更长一些。这种自动重传方式常称为**自动重传请求ARQ。**另外在停止等待协议中若收到重复分组,就丢弃该分组,但同时还要发送确认。
3)确认丢失和确认迟到:
- **确认丢失:**确认消息在传输过程中丢失。当A发送M1消息,B收到后,B向A发送了一个M1确认消息,但却在传输过程中丢失。而A并不知道,在超时计时过后,A重传M1消息,B再次收到该消息后采取以下两点措施:1、丢弃这个重复的M1消息,不向上层交付。2、向A发送确认消息。(不会认为已经发送过了,就不再发送。A能重传,就证明B的确认消息丢失)。
- **确认迟到:**确认消息在传输过程中迟到。A发送M1消息,B收到并发送确认。在超时时间内没有收到确认消息,A重传M1消息,B仍然受到并继续发送确认消息(B收到了2份M1)。此时A收到了B第二次发送的确认消息)。接着发送其他数据。过了一会儿,A收到了B第一次发送的对M1的确认消息(A也受到了2份去无人消息)。处理如下:1、A收到重复的确认后,直接丢弃。2、B收到重复的M1后,也直接丢弃重复的M1.
连续ARQ协议可提高信道通信利用率。发送方维持一个发送窗口,凡是位于发送窗口内的分组可以连续发送出去,而不需要等待对方确认。接收方一般采用累计确认,对程序到达的最后一个分组发送确认,表明到这个分组为止的所有分组都已经正确收到了。
**优点:**信道利用率高,容易实现,即使确认丢失,也不必重传。
**缺点:**不能向发送方反映出接收方已经正确收到的所有分组的信息。比如:发送方发送了5条消息,中间第三条丢失(3号),这时接收方只能对前两个发送确认。发送方无法知道后三个分组的下落,而只好把后三个全部重传一次。这也叫Go-Back-N(回退N),表示需要退回来重传已经发送过的N个消息。