传输层-TCP, TCP头部结构 ,TCP序列号和确认号详解
TCP主要解决下面的三个问题
1.数据的可靠传输。发送方如何知道发出的数据,接收方已经收到。
现实生活中,我们在打电话的时候,当我们自己根对方说了一句话或者一段话之后,我们都会等待对方的回应,譬如她们会回答"哦"、"嗯"、"知道了",这时我们就会知道对方已经听到我们自己刚才说的话,如果她们不给予回应则会以为她们没有在听我讲话,也就是没有收到我发送的消息。
TCP可靠传输的实现正是基于这样的例子,对于发送方发送的数据,接收方在接受到数据之后必须要给予确认,确认它收到了数据。如果在规定时间内,没有给予确认则意味着接收方没有接受到数据,然后发送方对数据进行重发。
重发: 当用户交给TCP传输的数据量很大时,如果使用简单的重发机制,即重发所有的数据,势必会严重占用和浪费带宽资源,甚至造成网络拥塞。因此TCP会将用户需要传输的数据进行分组,即将数据进行切割,分成多个数据段(data segment),并给每个数据段编号。
TCP报文段首部中通过长度为32bit的字段来表示这个TCP报文段的序号,另外通过长度为32bit的字段来表示确认报文段要确认的报文段的序号。
2.接收方的流量控制。因为各种原因,接收方可能来不及处理发送方发送的数据,而造成没有及时回应发送方,造成发送方不断的重发数据,最后造成接收方的主机宕机。
现实生活中,我们去一些热门的景点或者游乐园的某个娱乐项目时,都会需要进行排队,如果是小长假,则会出现人山人海的场景,这是这些机构就会控制每一次参观该景点的人数。网络应用程序也是如此,当数据到达主机之后,TCP会将该数据放入相应的队列(又称为缓冲区)(如果让你自己基于UDP实现一个TCP模块供自己的应用程序使用,你也会采用这种方式),等待监听该端口的应用程序从队列中获取数据,应用程序一次所能处理的数据有限,因此不可能一次性取出队列中的所有数据,当队列已经满了,则无法再存放新的数据,只能将接受到的数据丢弃,因此TCP协议需要提供流量控制的能力,控制发送方每次发送数据的大小。
3.计算机网络的拥塞控制。数据在计算机网络之上传输,当出现数据拥塞时如何进行处理
现实生活中,高速公路也会堵车,在一段高速公路上,每辆车都在以很快的速度在运行,彼此并没有慢下来,但是为什么还是会出现堵车呢?通常都是因为每段道路的承载能力不一样,譬如当一段8车道公路上的汽车行驶到4车道公路上时,在这两段道路交汇的地方就会出现堵车。
计算机网络是由无数的数据链路组成的,每一段链路的承载能力不一样,也会出现数据拥堵的情况,这通常是由路由器和交换机的处理能力不同造成的。我们还需要知道,这种情况下的拥塞是不能避免的,因为我们无法要求所有链路的承载能力一样,因此我们只能对拥塞进行控制。TCP协议对拥塞控制也提出了响应的解决方案,这也是为什么TCP叫做传输控制协议而不叫做可靠传输协议的原因吧,同时也解释了为什么在计算机网络可靠性能大大提供的今天,TCP还继续发挥着其作用的原因。
TCP连接管理
我们都说TCP是面向连接的,UDP不是面向连接的。那么什么是连接呢?为什么TCP需要面向连接呢?
连接是一个动作。现实生活中,我们想和一个通话,我们需要先拨打她的电话,等待她接听我们的打电话之后就可以进行通话了,当我们通话结束之后还需要挂断电话。
电话的连接会接通通信双方之间的电路,是一条真实存在的电路,在拆除这条电路之前,第三方是不能和两者之中的任何一方建立通信电路。和电话不同,TCP连接产生的通道是虚拟的,任何第三方端口都可以和两者之中的任何一个端口建立通道。我们称建立虚拟通道的过程为连接的建立。
连接是可靠传输的前提,而不是可靠传输的保证。在QQ这些聊天软件支持离线消息之前,人们在发送消息之前总要确保对方在线,因为如果对方不在线,消息根本就不会被对方收到,也就不存在对你发送的消息进行回应。TCP通过在连接这个动作让接收方知道发送方想要发送数据给它,如果接收方允许,则连接建立,这时双方之间便可以进行数据传输,接收到数据之后须确认数据收到。如果不建立连接,则无法实现可靠传输,因为对于发送方发送的数据,可能接收方的主机根本就没有在监听该端口。例如,在采用UDP的P2P实现中中仍然需要信令服务器,为什么需要信令服务器呢?因为对方可能根本就没有启动该P2P程序或者其它原因无法跟你进行通讯。简而言之,连接的作用就是让通讯双方知道并准备好通讯。
连接的建立-三次握手
TCP的可靠传输是通过确认和重传来实现的,因此
连接的建立过程
TCP连接的建立采用的是C/S(Client/Server,客户端/服务器)模型。由客户端发出建立连接的请求。
下面我们使用'ACK=1'这种方式来表示控制位中的相应位是否置1,'ACK=0'或者不说明则都为0。并使用'ack=1'这种方式表示TCP数据段首部中的确认序号,使用'seq=1'来表示TCP数据段首部中的发送序号。
Client首先向Server发出建立连接的TCP报文段(SYN=1,seq=x(表示随机产生一个值,我们假设为100)),并等待Server的确认(确认收到该建立连接的请求)
Server收到该建立连接的请求之后,如果同意建立连接,则发送TCP报文段(SYN=1,seq=y(也是随机产生一个值,我们假设为21),ACK=1,ack=x+1(这里表示发送方的x号数据段已经收到,这里为101))给Client表示确认接收到该TCP报文,并等待Client确认该TCP报文已经收到
Client收到Server的确认报文段之后,再次向Server发送TCP报文段(seq=x+1(这里为101),ACK=1,ack=y+1(这里为22)),确认Server的确认报文已经收到。
我们可以看到,控制字段中的SYN是用来建立一个TCP连接的,只在前两次"握手"中置为1,第三次"握手"置为0."我想和你谈话(SYN),我愿意和你谈话(SYN,ACK),那我们开始吧(ACK)".
连接的断开
通过TCP三次握手建立的通信属于全双工通信,因此每个方向都必须单独地进行关闭。关闭的原则就是当其中一方A完成数据的传输并且不再传输数据时,发送一个控制位FIN=1的TCP数据段来告知另一方B"我的数据已经传输完毕,并且不再传输数据",另一方B收到数据之后依旧发送确认TCP数据段,来表示A=>B方向的一条连接已经断开,此时TCP连接处于半关闭状态。需要注意的是,这里的不再传输数据是指A不再传输用户数据,对于B传输的数据,A仍然要接收并给予确认。
当B发送完数据之后并准备断开连接时,发送一个控制位FIN=1,ACK=1(ack=A的FIN报文段的序号)的TCP报文段,并等待A的确认,A收到B的FIN报文段后给予确认,至此整个TCP连接关闭。
为了防止因为数据传输延时造成B的FIN报文段比B的有效数据传输报文段(用户数据)提前到达,因A会等待2MSL之后才真正关闭TCP连接。
TCP的有限状态机
TCP连接建立:
- 首先,服务器监听一个TCP端口,此时该端口处于Listen状态。
- 一段时间后,客户端发送一个TCP连接请求,客户端的端口就出处于SYN_SENT状态,当服务器接收到一个客户端的TCP连接请求时,即收到客户端的SYN报文段,服务器监听的端口就会切换到SYN_RCVD状态,服务器向客户端发送SYN+ACK报文段==>问题0
- 当客户端收到服务器发送的SYN+ACK报文段时,客户端的端口切换到ESTAB-LISTEN状态,客户端同时向服务器发送SYN报文段确认 ==>问题1
- 当服务器收到客户端的ACK报文段时,服务器的端口切换到ESTAB-LISTEN状态。
问题0:当客户端发送的SYN报文段,没有得到服务器的任何响应怎么办获者收到服务器的REST响应当客户端发送一个SYN报文段之后就会启动定时器,如果在规定的时间内没有收到服务器的任何响应或者收到服务器的RESR响应,则会重新发送SYN报文段。如果在几次重发后仍然没有得到服务器的SYN+ACK响应就会放弃,端口切换CLOSE状态,并报告上层。
问题1:如果当客户端发送给服务器的SYN报文段丢失了会怎样?
连接仍然能正常工作。因为客户端已经处于ESTABLISHED状态,所以客户端能够像服务器发送数据。由于每个TCP报文段中都有ACK标识位,而在确认序号字段中包含正确的数值。所以当客户端发送的第一个数据到达服务器时,服务器的端口就会切换到ESTABLISHED状态。这实际上是TCP的重点,即每个TCP报文段报告发送方希望看到的下一个序号,即使这个序号与以前的一个或多个报文段包含的序号重复。**
TCP的可靠传输
TCP的可靠传输是通过确认和超时重传的机制来实现的,而确认和超时重传的具体的实现是通过以字节为单位的滑动窗口机制来完成。
滑动窗口机制
虽然上层应用和TCP的交互是一次一个数据快(大小不等),但是TCP把上层应用程序交付下来的数据看成仅仅是一串连续的无结构字节流。
发送窗口:在未收到对方的ACK确认的情况下,只有发送窗口内的数据才能连续地发送出去。凡事已经发送过的数据,在未收到ACK确认之间都必须暂时保留在发送窗口内,以便超时重传使用。
-
接收窗口:缓冲区,用来接收发送方的TCP数据段。
停止-等待协议
发送方和接收方都采用窗口大小为1的滑动窗口,即发送窗口和接受窗口都为1个最大TCP数据段的大小。
停止等待协议的规则是:
- 发送方发完1个分组并收到接收方ACK确认之后才能发送下一个分组;
- 如果接收方收到一个错误的分组,则给发送方发送一个否认分组NAK,发送方收到NAK分组后重发,并继续等待发送方的ACK确认
- 如果发送方在规定的时限内(发送完一个分组,就开启一个定时器)没有收到接收方的ACK确认分组,则重新发送该分组。
后退N协议
后退N协议的思想是流水线传输,即可以连续发送多个分组,而不必每发完一个分组就等待接收方的ACK确认。
规则如下:
- 发送窗口的大小为n,接收窗口的大小为1
- 发送方在发送完一个数据分组之后,不是停下来等待接收方的ACK确认,而是可以连续再发送若干个分组。
- 接收方在收到发送方发送的分组之后发送ACK确认分组,并移动接收窗口。
- 如果发送方发送一共连续发送了4个分组,中间的第2个分组丢失,则接收方要求发送方重传后面的3个分组(第2个、第3个、第4个分组)。(因为第3个和第4个分组不接序)这也说明了该协议为什么叫做后退N协议。
描述:
虽然在收到了有差错的2号分组之后,收到了正确的3号分组和4号分组,但是由于接收端只按顺序接收数据分组,造成3号和4号分组不能和1号分组接序而被丢弃,等到A的定时器超时重发。
选择重传
选择重传协议是对后退N协议的一种优化,其只是选择性重发那些确实丢失的分组。
规则:
- 发送窗口的大小为m,接收窗口的大小为n
- 接收方先接收序号不连续的分组,并发送ACK确认,然后等待发送方重发丢失的分组(发送方每收到一个ACK确认就会关闭相应的定时器,最终没有收到ACK确认的分组的定时器超时,发送方会再次重发)
- 收到重发的分组后给予ACK确认,再对全部分组进行排序,最后交给上层应用。
通知窗口
TCP采用通知窗口实现对发送端的流量控制,通知窗口大小的单位是字节。TCP通过在TCP数据段首部的窗口字段中填入当前设定的接收窗口(即通知窗口)的大小,用来告知对方'我方当前的接收窗口大小',以实现流量控制。
通信双方的发送窗口大小由双方在连接建立是商定,在通信过程,双方可以动态地根据自己的情况调整对方的发送窗口大小。
TCP拥塞控制
在某段时间,如果对计算机网络中某些资源的需求超过了所能提供该资源的总和,网络的性能就要变坏——产生拥塞(congestion)。即当需要>供给时会造成网络拥塞。如果计算机网络中有许多资源同时产生拥塞,网络的性能就要明显变坏,整个网络的吞吐量将随输入负荷的增大而下降。
TCP协议通过慢启动机制、拥塞避免机制、加速递减机制、快重传和快恢复机制来共同实现拥塞控制。
在拥塞控制中还有一个"拥塞窗口"的概念,该窗口由发送方根据当前计算机网络的拥塞情况来计算,和通知窗口共通作用于发送窗口,"拥塞窗口"的单位也是字节,通常拥塞窗口的初始值为一个最大TCP报文段的大小是,但下面我们以每个传输轮次所能发送TCP数据段(用户数据)的次数作为其单位来描述。
TCP的慢启动机制、拥塞避免机制和加速递减机制都是通过改变拥塞窗口的大小来时对发送方的发送窗口进行控制。
拥塞控制与流量控制的关系
拥塞控制是一个全局性的控制,涉及到计算机网络中所有的主机、路由器以及降低网络传输性能的相关因素。而流量控制只涉及到通信双方之间的收发平衡。
TCP在控制数据传输时,既要考虑接收端的接收能力,又要避免网络拥塞,因而发送方的发送窗口大小为通知窗口和拥塞窗口的最小值。
传输轮次
在TCP的拥塞避免中,我们规定:每发送拥塞窗口值个数的TCP数据段(有效数据承载),并且全部收到发送方对这些数据的ACK确认,我们就称完成了1个传输轮次。
例如,拥塞窗口=4,当发送方发送了4个TCP报文段,并收到这4个TCP报文段的ACK确认,我们就称完成了一个传输轮次。
慢启动机制
慢启动通过逐步增大拥塞窗口的值来控制网络拥塞。
慢启动机制规定:
- 拥塞窗口的初始值为1
- 每收到一个对发出的数据段的ACK确认,便将拥塞窗口的值增加1倍
我们可以发现,每完成一次传输轮次,拥塞窗口的值就翻倍,即拥塞窗口随着传输轮次的增加成指数增长。
随着传输轮次的增加,拥塞窗口的值会变得很大,因此TCP拥塞控制給慢启动增加一个阈值(又称慢启动门限),当拥塞窗口>阈值时,就要进行尝试拥塞避免。
当 拥塞窗口 < 阈值 时,使用慢启动算法
当 拥塞窗口 > 阈值 时,使用拥塞避免算法
当 拥塞窗口 = 阈值时,既可以使用慢启动算法,也可时使用拥塞避免算法。
随着网络拥塞的出现和变化,阈值也会不断变化。TCP拥塞控制中,阈值的初始值为16
拥塞避免
拥塞避免算法的思路是让拥塞窗口缓慢地增大,呈线性增长,即每完成一个传输轮次,拥塞窗口增加1。
拥塞避免是指在拥塞避免阶段把拥塞窗口控制为按线性规律增长,使网络比较不容易出现拥塞,而不是完全能够避免拥塞。
加速递减机制
如果在使用慢启动机制或者拥塞避免机制中,发送数据时,出现了定时器超时,便执行加速递减机制:
- 立刻将慢启动门限置为当前拥塞窗口大小的一般,然后拥塞窗口的值重置为1
- 执行使用慢启动机制
快重传和快恢复
如果发送方设置定时器超时,那么很可能是网络出现了拥塞,致使TCP报文段在网络中的某处被丢弃。在这种情况下,TCP马上把拥塞窗口减少到1,并执行慢开始算法,同时慢开始门限值减半。这是不采用快重传机制的情况:
快重传机制要求接收方每收到一个失序的TCP报文段后就立即发出重复确认(为了使发送方及早知道没有到达对方)而不要等待自己发送数据时才进行确认。
快重传算法规定:发送方只要连续收到3个重复确认就应当立即重传未被确认的报文段。
快恢复
当发送端收到连续三个重复的确认时,就执行“乘法减小”算法,把慢开始门限 ssthresh 减半。但接下去不执行慢开始算法。
由于发送方现在认为网络很可能没有发生拥塞,因此现在不执行慢开始算法,即拥塞窗口 cwnd 现在不设置为 1,而是设置为慢开始门限 ssthresh 减半后的数值,然后开始执行拥塞避免算法(“加法增大”),使拥塞窗口缓慢地线性增大。
TCP习题
A,B两台机器都正常工作,B机器未监听任何端口.如果A机器向B机器80端口发送SYN包,会收到何种类型的回包?
RST包
TCP建立连接的过程采用三次握手,已知第三次握手报文的发送序列号为1000,确认序列号为2000,请问第二次握手报文的发送序列号和确认序列号分别为?
1999,1000
某一速率为100M的交换机有20个端口,其一个端口上连着一台笔记本电脑,此电脑从迅雷上下载一部1G的电影需要的时间可能是多久?
交换机为独占带宽,即每个端口数据通过率为为最大100Mb/s。注意单位是Mb。因此最短时间为:
1GB/(100Mb/s)=1024MB/(12.5MB/s)=81.92s。
这里涉及到单位换算问题
消息传递部分为三个功能级?
第一级为数据链路功能级,第二级是信令链路功能级,第三级是信令网功能级
最后对tcp头结构做一些补充说明
TCP头部结构
TCP头部信息出现在每个TCP报文段中,用于指定通信的源端端口,目的端端口,管理TCP连接等,本节详细介绍TCP的头部结构,包括固定头部结构和头部选项。
TCP固定头部结构
TCP头部结构如图3-3所示,其中的诸多字段为管理TCP连接和控制数据流提供了足够的信息。
16位端口号(port number):告知主机该报文段是来自哪里(源端口)以及传给哪个上层协议或应用程序(目的端口)的。进行TCP通信时,客户端通常使用系统自动选择的临时端口号,而服务器则使用知名服务端口号。1.3节中提到过,所有知名服务使用的端口号都定义在/etc/services文件中。
32位序号(sequence number):一次TCP通信(从TCP连接建立到断开)过程中某一个传输方向上的字节流的每个字节的编号。假设主机A和主机B进行TCP通信,A发送给B的第一个TCP报文段中,序号值被系统初始化为某个随机值ISN(Initial Sequence Number,初始序号值)。那么在该传输方向上(从A到B),后续的TCP报文段中序号值将被系统设置成ISN加上该报文段所携带数据的第一个字节在整个字节流中的偏移。例如,某个TCP报文段传送的数据是字节流中的第1025~2048字节,那么该报文段的序号值就是ISN+1025。另外一个传输方向(从B到A)的TCP报文段的序号值也具有相同的含义。
32位确认号(acknowledgement number):用作对另一方发送来的TCP报文段的响应。其值是收到的TCP报文段的序号值加1。假设主机A和主机B进行TCP通信,那么A发送出的TCP报文段不仅携带自己的序号,而且包含对B发送来的TCP报文段的确认号。反之,B发送出的TCP报文段也同时携带自己的序号和对A发送来的报文段的确认号。
4位头部长度(header length):标识该TCP头部有多少个32bit字(4字节)。因为4位最大能表示15,所以TCP头部最长是60字节。
6位标志位包含如下几项:
- URG标志,表示紧急指针(urgent pointer)是否有效。
- ACK标志,表示确认号是否有效。我们称携带ACK标志的TCP报文段为确认报文段。
- PSH标志,提示接收端应用程序应该立即从TCP接收缓冲区中读走数据,为接收后续数据腾出空间(如果应用程序不将接收到的数据读走,它们就会一直停留在TCP接收缓冲区中)。
- RST标志,表示要求对方重新建立连接。我们称携带RST标志的TCP报文段为复位报文段。
- SYN标志,表示请求建立一个连接。我们称携带SYN标志的TCP报文段为同步报文段。
- FIN标志,表示通知对方本端要关闭连接了。我们称携带FIN标志的TCP报文段为结束报文段。
16位窗口大小(window size):是TCP流量控制的一个手段。这里说的窗口,指的是接收通告窗口(Receiver Window,RWND)。它告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度。
16位校验和(TCP checksum):由发送端填充,接收端对TCP报文段执行CRC算法以检验TCP报文段在传输过程中是否损坏。注意,这个校验不仅包括TCP头部,也包括数据部分。这也是TCP可靠传输的一个重要保障。
16位紧急指针(urgent pointer):是一个正的偏移量。它和序号字段的值相加表示最后一个紧急数据的下一字节的序号。因此,确切地说,这个字段是紧急指针相对当前序号的偏移,不妨称之为紧急偏移。TCP的紧急指针是发送端向接收端发送紧急数据的方法。我们将在后面讨论TCP紧急数据。
补充实际数据包分析 结合上面的理论,下面我们访问网页来捕获数据包,通过实际的数据包来验证序列号和确认号在TCP连接建立、传输数据以及关闭连接时的变化。打开科来网络分析系统,首先为减少数据干扰,在过滤器中设置只捕获TCP协议的数据,然后开始捕获,同时,访问www.csna.cn ,待页面下载完成后,停止捕获。此次环境中,客户端为192.168.0.92,服务器为:222.77.187.23。3.1 TCP建立连接 在捕获的数据包中,首先我们来查看建立连接的三次握手信息,并且观察数据包中序列号和确认号的变化。为了让大家看的更加明白,我在这里使用了“添加数据包注释”的功能。我们先来查看建立连接的第一步,如图1所示。