TCP-连接、断开和滑动窗口简介

1.TCP概述

  TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP提供全双工服务即A和B都可以主动给对方发送数据(可以和HTTP协议做对比,一般情况是只能客户端给服务器发送数据【h5新加入的websocket可以双向通信】)。TCP的控制信息存储在TCP报文的首部,其格式如下图所示

  每个TCP段都包含源端和目的端的端口号,用于寻找发端和收端应用进程。这两个值加上IP首部中的源端IP地址和目的端IP地址唯一确定一个TCP连接(IP地址+断开号也即Socket)。

  序号是32 bit的无符号数,序号到达232-1后又从0开始。也就是说序号是用mod 232运算的。TCP是面向字节流的,在一个TCP连接中传送的每一个字节都按顺序编号。整个要传送的字节流的起始序号必须在连接建立时设置。TCP报文首部中的序号就是此报文段所发送数据的第一个字节的序号。例如,一个报文段的序号字段值是1,共携带1440个字节数据数据,则此报文段的第一个字节序号为1,最后一个字节的序号为1440。显然下一个报文段(如果还有的话)序号应当从1441开始。序号是用来解决网络包乱序问题而确认号用于确认收到,用来解决丢包问题。如果发端在一定时间内没有收到收端的确认则会将数据重传。(需要注意的是确认号,许多文章都简单的介绍了确认号=发端序号+1,其实确认号是应当是发端数据最后一个字节的序号+1,还是上面的例子发送时序号=1,确认号会是1441,即确认号是和发送数据长度有关的)。

  TCP首部的6个标志位分别是:

TCP标志位中:

  ACK:TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1.

  SYN:在连接建立时用于同步序号。当SYN=1 ACK=0时,表示这是一个连接请求报文,若对方同意建立连接,则响应报文中应使SYN=1 ACK=1.因此,SYN置1表示这是一个连接请求或连接接受报文。

  FIN:即完成终结的意思,用来释放连接。当FIN=1时,表明此报文段的发送方的数据已经发送完毕,并要求释放连接。

  窗口(Advertised-Window):与本文最后会介绍的滑动窗口有关,它用于传送过程中数据流的控制。

2.建立连接(TCP三次握手)

  首先客户端发出连接请求,置TCP标志位SYN=1 ACK=0,TCP规定SYN=1时不能携带数据,但要消耗一个序号,因此声明自己的序号seq=x,发送连接请求后客户端状态由Closed变为SYN-SENT,此即第一次握手。服务器收到请求后发现SYN=1知道是一个连接请求,进行回复确认即置SYN=1 ACK=1 声明自己的序号seq=y,确认号为ack=x+1,此时服务器状态由LISTEN变为SYN-RCVD,此即第二次握手。客户端收到服务器的连接确认后,检查确认号ack是否正确即第一次发送的序号+1(x+1),以及标志位ACK是否为1,若正确,则向服务器发送确认包置标志位ACK=1 SYN=0,序号seq=x+1,确认号ack=y+1,发送确认信息后客户端状态由SYN-SENT变为ESTABLISHED,此即第三次握手。服务器收到确认信息后状态由SYN-RCVD变为ESTABLISHED,至此连接建立。(注:文中大写ACK表示TCP标志位,小写ack表示确认号)

  为什么要进行三次握手呢(两次确认,服务器确认、客户端确认)?客户端的再一次确认是为了防止已失效的连接请求报文段突然又传送到服务器,从而产生错误。所谓"已失效的连接请求报文段"是这样产生的。考虑一种正常情况,客户端发出连接请求,但因连接请求报文丢失而未收到服务器的恢复确认。于是客户端重传一次连接请求,收到确认后建立连接,开始数据传输,数据传送完毕后释放了连接,此例中客户端共发送了两个连接请求,一个丢失一个到达服务器端。没有"已失效的连接请求报文段"产生。现假定出现一种异常情况,即客户端发出的第一个连接请求没有丢失而且在某些网络节点长时间滞留了,以致延误到连接请求释放以后的某个时间到达服务器。本来是一个早已失效的报文段,但服务器收到此失效报文段后,误认为是客户端又发出一个新的连接请求,于是向客户端发出回复确认,同意建立连接。假定不采用三次握手,那么只有服务器端发出确认,新的连接就建立了。由于现在客户端并没有发出建立连接的请求,因此不会理财服务器的确认,也不会向服务器发送数据。但服务器以为新的连接已经建立,并一直等待客户端发来数据,从而造成服务器资源的浪费,但采用三次握手的方法可以防止上述现象的发生。例如在刚才的情况下,客户端不会向服务器的确认再次确认,服务器由于收不到确认,就知道客户端没有要求建立连接。

3.断开连接(TCP四次挥手)

   

  当客户端已经没有数据要发送时就要释放它的连接,此时它会发送一个报文(没有数据),置标志位FIN=1 ACK=1设置序号seq=u,确认号ack=v,此时状态由ESTABLISHED变为FIN-WAIT-1。服务器接收到信息后了解到客户端请求释放连接,但此时可能还有数据没有传送完成,所以先回复ACK报文,置ACK=1,序号为seq=收到的确认号=v,确认号ack=收到的序号+1=u+1,此时状态由ESTABLISHED变为CLOSE-WAIT。客户端收到服务端的ACK报文后状态由FIN-WAIT-1变为FIN-WAIT-2并继续等待服务器的FIN信号,此期间客户端还是可以接收服务端发送的数据的。当服务端所有数据传送完成后会发送FIN报文,置FIN=1 ACK=1,序号seq=w,确认号ack=u+1,此时状态由CLOSE-WAIT变为LAST-ACK。客户端收到服务端的FIN报文后会发送确认报文,置ACK=1,序号seq=u+1,确认号ack=w+1,此时状态由FIN-WAIT-2变为TIME-WAIT,之后客户端在等待2MSL(最大报文生命周期)的时间后会关闭,状态变为CLOSED。服务器收到客户端最后的确认信息后会直接关闭,状态变为CLOSED。(注意当一方主动关闭后会经历TIME-WAIT一段时间才可以关闭,被动关闭方收到最后确认报文后则直接关闭)。

  综合以上内容总结TCP生命周期的状态转换图如下

4.滑动窗口

  将TCP与UDP这样的简单传输协议区分开来的是它传输数据的质量。TCP对于发送数据进行跟踪,这种数据管理需要协议有以下两大关键功能:

  可靠性:保证数据确实到达目的地。如果未到达,能够发现并重传。

  数据流控:管理数据的发送速率,以使接收设备不致于过载。

  要完成这些任务,整个协议操作是围绕滑动窗口确认机制来进行的。TCP通过滑动窗口机制检测丢包,并在丢包发生时调整数据传输速率。本文开始部分提到TCP首部有一个窗口字段即对应滑动窗口,这个字段是收端告诉发端自己还有多少缓冲区可以接收数据。于是发端就可以根据收端的处理能力来发送数据,而不会导致收端无法处理造成丢包现象。为了说明滑动窗口机制,首先我们来看一下TCP缓冲区的数据结构:

图中我们可以看到:

  • 收端LastByteRead指向了TCP缓冲区中读到的位置(即缓冲区中此位置之前的数据已被消费),NextByteExpected指向的地方是收到的连续包的最后一个位置,LastByteRcved指向的是收到的包的最后一个位置,我们可以看到中间有些数据还没有到达,所以有数据空白区。
  • 发端的LastByteAcked指向了被收端Ack过的位置(表示成功发送确认),LastByteSent表示发出去了,但还没有收到成功确认的Ack,LastByteWritten指向的是上层应用正在写的地方。

于是:

  • 收端在给发端的ACK中会回报自己的AdvertisedWindow(写入本文开头提到的TCP首部的窗口字段) = MaxRcvBuffer – LastByteRcvd – 1;
  • 而发端会根据这个窗口来控制发送数据的大小,以保证收端可以正常处理。

下面我们来看一下发送方滑动窗口示意图:

图中分为四个部分,分别是:(其中那个黑模型是发端窗口,当收到确认ACK后整个黑框会整体向右移动,因此成为滑动窗口)

  • #1已发送并收到ack确认的数据
  • #2已发送但还未收到ack确认的数据。
  • #3未发送但收端已准备好接收的数据(即收端窗口大小-已发送但未收到确认的数据大小=即收端窗口当前可用大小)或者叫窗口中尚未发送数据。
  • #4未发送收端也没有准备好接收的数据或者叫窗口外数据(发端要发送的内容但是接收方缓冲区已没有空间)。

下面是个滑动后的示意图(收到36的ack,并发出了46-51的字节。注意这是收端ACK中未改变AdvertisedWindow的情况):

下面我们来看一个收端控制发端的图示(收端改变AdvertisedWindow的情况):

由上图可知,发端的窗口大小是受收端窗口大小控制的,当收端收到数据但是数据没有被消费时,由于数据在缓冲区滞留,剩余可用空间减少,为控制流量收端将通知发端减小AdvertisedWindow的大小,发端收到信号后整体滑动窗体大小缩小,直至减少为0将不再发送数据。当TCP首部窗口字段减少到0后,发端将使用Zero Window Probe(0窗口探测)技术简称ZWP,发送ZWP包告诉收到我还keep-alive,收端收到ZWP包后会报告其窗口大小,如果若干次后窗口大小还是0,则TCP实现就会发RST把链接断掉。

  滑动窗口是TCP协议中一个重点也是比较难掌握的概念,下面将插入一个动画演示来让大家加深理解。

最后本文引用了很多作者内容加上自己的理解,如有需要说明,我将及时处理。

时间: 2024-08-04 15:33:50

TCP-连接、断开和滑动窗口简介的相关文章

TCP建立连接的三次握手和TCP连接断开的四次挥手

1. TCP建立连接的3次握手 2. TCP断开连接的四次挥手 [注意]中断连接端可以是Client端,也可以是Server端. 图3-Client端主动发起关闭连接请求 1. 假设Client端主动发起中断连接请求,也就是发送FIN报文. 2. Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据.所以你先发送ACK,"告诉Client端,你的请求我收到了,但是我还没准备

TCP数据量--滑动窗口、拥塞窗口、慢启动、Negle算法 经受时延的确认等

TCP的数据流大致可以分为两类,交互数据流与成块的数据流.交互数据流就是发送控制命令的数据流,比如relogin,telnet,ftp命令等等:成块数据流是用来发送数据的包,网络上大部分的TCP包都是这种包. 很明显,TCP在传输这两种类型的包时的效率是不一样的,因此为了提高TCP的传输效率,应该对这两种类型的包采用不同的算法. 总之,TCP的传输原则是尽量减少小分组传输的数量. TCP的交互式数据流 ?         经受时延的确认技术 TCP的交互式数据流通常使用"经过时延的确认"

TCP滑动窗口 [转]

1. 滑动窗口其实是一种协议,它主要提供两个作用,一是提供TCP的可靠性,二是提供TCP的流量控制特性,我感觉因为其协议动作特征类似窗口在移动所以称为滑动窗口.如图,从TCP首部可以看到滑动窗口的大小占16位,故其最大为2^16-1即65535个字节,另外在TCP的选项字段中还包含了一个TCP窗口扩大因子,窗口扩大因子用来扩大TCP窗口,可把原来16bit的窗口,扩大为31bit. 2. 滑动窗口可以分为发送窗口和接收窗口,因为TCP是双工的协议,所以TCP会话的双方都各自维护一个"发送窗口&q

TCP的滑动窗口机制【转】

原文链接:http://www.cnblogs.com/luoquan/p/4886345.html      TCP这个协议是网络中使用的比较广泛,他是一个面向连接的可靠的传输协议.既然是一个可靠的传输协议就需要对数据进行确认.TCP协议里窗口机制有2种:一种是固定的窗口大小:一种是滑动的窗口.这个窗口大小就是我们一次传输几个数据.对所有数据帧按顺序赋予编号,发送方在发送过程中始终保持着一个发送窗口,只有落在发送窗口内的帧才允许被发送:同时接收方也维持着一个接收窗口,只有落在接收窗口内的帧才允

TCP可靠传输:校验和,重传控制,序号标识,滑动窗口、确认应答

Tcp通过校验和,重传控制,序号标识,滑动窗口.确认应答实现可靠传输 应答码:ACK TCP的滑动窗口机制       TCP这个协议是网络中使用的比较广泛,他是一个面向连接的可靠的传输协议.既然是一个可靠的传输协议就需要对数据进行确认.TCP协议里窗口机制有2种:一种是固定的窗口大小:一种是滑动的窗口.这个窗口大小就是我们一次传输几个数据.对所有数据帧按顺序赋予编号,发送方在发送过程中始终保持着一个发送窗口,只有落在发送窗口内的帧才允许被发送:同时接收方也维持着一个接收窗口,只有落在接收窗口内

TCP滑动窗口控制流量的原理

TCP滑动窗口控制流量的原理 TCP的滑动窗口机制       TCP这个协议是网络中使用的比较广泛,他是一个面向连接的可靠的传输协议.既然是一个可靠的传输协议就需要对数据进行确认.TCP协议里窗口机制有2种:一种是固定的窗口大小:一种是滑动的窗口.这个窗口大小就是我们一次传输几个数据.对所有数据帧按顺序赋予编号,发送方在发送过程中始终保持着一个发送窗口,只有落在发送窗口内的帧才允许被发送:同时接收方也维持着一个接收窗口,只有落在接收窗口内的帧才允许接收.这样通过调整发送方窗口和接收方窗口的大小

Tcp连接的断开

Tcp连接断开的四次挥手 1 client端向server端发送FIN请求断开连接,client端进入FIN_WAIT_1状态,等待server端的ACK.此时客户端 不能发送数据,但仍然能够从server端读取数据. 2 server端收到FIN并发送了ACK之后,进入close_wait状态,不能够在读取数据,但仍然能向client发送数据. 3 client端收到了server端的ACK以后,进入FIN_WAIT_2状态,等待server端的FIN.server端发送FIN后进入 LAST

FTP协议的粗浅学习--利用wireshark抓包分析相关tcp连接

一.为什么写这个 昨天遇到个ftp相关的问题,关于ftp匿名访问的.花费了大量的脑细胞后,终于搞定了服务端的配置,现在客户端可以像下图一样,直接在浏览器输入url,即可直接访问. 期间不会弹出输入用户名密码来登录的窗口. 今天我主要是有点好奇,在此过程中,究竟是否是用匿名账户“anonymous”该账户登录了,还是根本不需要登录呢? 于是用wireshark抓包了一下. 二.抓包过程 我这边直接用了捕获过滤器抓本机和ftp之间的包.抓包后直接ctrl+F进行文本查找. 果然发现是发送了USER

粘包、拆包发生原因滑动窗口、MSS/MTU限制、Nagle算法

[TCP协议](3)---TCP粘包黏包 有关TCP协议之前写过两篇博客: 1.[TCP协议](1)---TCP协议详解 2.[TCP协议](2)---TCP三次握手和四次挥手 一.TCP粘包.拆包图解 假设客户端分别发送了两个数据包D1和D2给服务端,由于服务端一次读取到字节数是不确定的,故可能存在以下四种情况: 1)服务端分两次读取到了两个独立的数据包,分别是D1和D2,没有粘包和拆包 2)服务端一次接受到了两个数据包,D1和D2粘合在一起,称之为TCP粘包 3)服务端分两次读取到了数据包,