3 运输层(二)

4 可靠数据传输原理

可靠数据传输的实现问题不仅在运输层出现,也会在链路层以及应用层出现。

可靠数据传输的框架:为上层实体提供的服务抽象是:数据可以通过一条可靠的信道进行传输。实现这种服务抽象是可靠数据传输协议的责任。

由于可靠数据传输协议的下层协议也许是不可靠的,因此这是一项困难的任务。TCP是在不可靠的IP端到端网络层之上实现的可靠数据传输协议。更一般的情况是,两个可靠通信端点的下层可能是由一条物理链路组成或是由一个全球互联网络组成。

下面讨论基于以下假设:分组将以发送它们的次序进行交付,某些可能丢失。这就是说,底层信道将不会对分组重排序。

4.1 构造可靠数据传输协议

4.1.1 经完全可靠信道的可靠数据传输:rdt1.0

有限状态机(Finite-State-Machine,FSM)

该发送方和接收方的FSM每个都只有一个状态。FSM描述图中的箭头指示了协议从一个状态变迁到另一个状态(上图每个FSM都只有一个状态,因此变迁的必定是从一个状态返回到自身。)

引起变迁的事件显示在表示变迁的横线上方,事件发生时所采取的动作显示在横线下方。如果对一个事件没有动作,或没有事件就在横线上方或者下方用^符号表示。

1)在发送端:rdt的发送端只通过rdt_send(data)事件接收来自较高层的数据,产生一个包含该数据的分组(经由make_pkt(data)动作),并将分组发送到信道中。实际上,rdt_send(data)事件是由较高层应用过程调用产生的。

2)在接收端:rdt通过rdt_rcv(packet)事件从底层信道接收一个分组,从分组中取出数据(经由extract(packet,data)动作),并将数据上传给较高层(通过deliver_data(data)动作)。实际上,rdt_rev(packet)事件是由较底层协议的过程调用产生的。

4.1.2 经具有比特差错信道的可靠数据传输:rdt2.0

底层信道更为实际的模型是分组中的比特可能受损。在分组的传输、传播或缓存的过程中,这种比特差错通常会出现在网络的物理部件中。

利用控制报文使得接收方可以让发送方知道哪些内容被正确接收,哪些内容接收有误并因此需要重复。在计算机网络中,基于这样重传机制的可靠数据传输协议称为自动重传请求(Automatic Repeat reQuest,ARQ)协议。

ARQ协议还需要另外三种协议来处理存在比特差错的情况:

1)差错检测:这些技术需要有额外的比特(除了待发送的初始数据比特之外的比特)从发送方发送到接收方;这些比特将被汇集在rdt2.0数据分组的分组检验和字段中。

2)接收方反馈:rdt2.0协议将从接收方向发送方回送ACK(“肯定确认”)或者NAK(“否定确认”)分组。理论上,这些分组只需要一个比特长;用0表示NAK,用1表示ACK。

3)重传:接收方收到有差错的分组时,发送方将重传该分组文。

rdt2.0的发送端FSM有两个状态,接收方FSM有一个状态。但是注意以下事实:

1)当发送方处于等待ACK或NAK的状态时,它不能从上层获得更多的数据。这就是说rdt_send()事件不可能出现,仅当接收到ACK并离开该状态时才能发生这样的事件。因此,发送方将不会发送一块新数据,除非发送方确信接收方已正确接收当前分组。rdt2.0协议被称为停等(stop-and-wait)协议。

2)它存在一个致命的缺陷,尤其是没考虑到ACK或NAK分组受损的可能性。

下面考虑ACK或者NAK时的3种可能:

1)

2)增加足够的检验和比特,使发送方不仅可以检测错误,还可以恢复差错。(这对于产生差错但不丢失分组的信道,这就可以直接解决问题。)

3)当发送方收到含糊不清的ACK或NAK分组时,只需重传当前数组分组即可。然而这种方法在发送方到接收方的信道引入可冗余分组:冗余分组的困难在于接收方不知道上次发送的ACK或NAK是否被发送方正确的收到。(解决办法是:在数据分组中添加一个新字段,让发送方对其数据分组编号,即将发送数据分组的序号放在该字段。于是,接收方只需要检查序号即可确定收到的分组是否一次重传。)

对于停等协议,1比特就够了,因为它可以让接收方知道发送方是否正在重传一个发送分组,或是一个新分组。

下面是rdt2.1的FSM描述:

下面是rdt2.2的FSM描述:

4.1.3 经具有比特差错的丢包信道的可靠数据传输:rdt3.0

现在假定除了比特受损外,底层信道还会丢包。协议现在必须处理另外两个关注的问题:怎样检测丢包以及发生丢包后该做些什么。在rdt2.2中已经研发的技术:使用校验和、序号、ACK分组和重传等。使得可以解决第二个问题,对于第一个问题,还需要增加一种新的协议机制:

对于第一个问题:解决丢包问题,可以让发送方负责检测和恢复丢包工作。假定发送方传输一个数据分组,该分组或者接受方对该分组的ACK发生了丢失。这两种情况发送方都收不到应当到来的接收方的响应。如果发送方愿意等待足够长的时间以便确定分组已丢失,则它只需重传该数据分组即可。

对于第二个问题:发送方需要等待的时间:发送方与接收方之间的一个往返时延加上接收方处理一个分组的时间(有时该时延很长)。因此,实践中的做法是发送方选择一个时间值,以判定可能发生了丢包。如果在这个时间内没有收到ACK,则重传分组。这就在发送方到接收方的信道中引入了冗余数据分组。这个问题在rdt2.2中已经解决。

从发送方来看,重传是一种很好的方式。为了实现基于时间的重传机制,需要一个倒数定时器,在一个给定的时间量过期后,可中断发送方。因此发送方需要做到:

1)每次发送一个分组(包括第一次分组和重传分组)时,便启动一个定时器。

2)响应定时器中断。

3)终止定时器。

rdt3.0有时被称为比特交替协议(alternating-bit protocol)

数据传输协议的要点:在检验和、序号、定时器、肯定和否定确认分组这些技术中,每种机制都在协议的运行中起到了必不可少的作用。

4.2 流水线可靠数据传输协议

rdt3.0 性能问题的核心在于它是一个停等协议。

停等协议的缺点在于其利用率(发送方实际忙于将发送比特送进信道的那部分时间与发送时间之比)。

解决这种特殊的性能问题的一个简单方法是:不使用停等方式运行,允许发送方发送多个分组而无需等待确认。这种技术为流水线:因为许多从发送方向接收方输送的分组可以被看成是填充到一条流水线中。

流水线技术对可靠数据传输协议带来如下影响:

1)必须增加序号范围:因为每个输送中的分组必须有一个唯一的序号,而且也许有多个在输送中未确认的报文。

2)协议的发送方和接收方两端也许必须缓存多个分组。

3)所需序号范围和对缓冲的要求取决于数据传输协议如何处理丢失、损坏及延时过大的分组。

解决流水线的差错恢复有两种基本的方法:回退N步(G0-Back-N,GBN),和选择重传(Selective Repeat,SR)。

4.3 回退N步

这里暂时不太清楚,后续加上。

4.4 选择重传

这里暂时不太清楚,后续加上。

5 面向连接的运输TCP

TCP是因特网运输层的面向连接的可靠运输协议。TCP依赖很多原理:其中包括差错检测、重传、累积确认、定时器以及用于序号和确认号的首部字段。TCP定义在RFC793、RFC1122、RFC1323、RFC2018、以及RFC2581中。

5.1 TCP连接

TCP被称为是面向连接的(connection-oriented),这是因为在一个应用进程可以开始向另一个应用进程发送数据之前,这两个进程必须先互相“握手”(即它们必须相互发送某些预备报文段,以建立确保数据传输的参数)。作为TCP连接建立的一部分,连接双方都将初始化与TCP连接相关的许多TCP状态。

传输控制协议/网际协议(Transmission Control Protocal/Internet Protocal,TCP/IP)

1)由于TCP协议只在端系统中运行,而不在中间的网络元素(路由器和链路层交换机)中运行,所以中间的网络元素不会维持TCP连接状态。

2)TCP连接提供的是全双工服务(full-duplex service):如果一台主机的进程A与另一台主机上的进程B存在一条TCP连接,则应用层数据就可在进程B流向进程A的同时,也从进程A流向进程B。

3)TCP连接总是点对点(point-to-point)的,即在单个发送方与单个连接方之间连接。

4)假设运行在某台主机上的一个进程想与另一台主机上的一个进程建立一条连接,该客户应用进程首先通知客户运输层,它想与服务器上的一个进程建立一条连接。一个客户程序通过发出下面的命令来实现
clientSocket.connect((serverName,serverPort))

5)三次握手:客户首先发送一个特殊的TCP报文段,服务器用另一个特殊的TCP报文段来相应,最后,客户再用第三个特殊报文段作为响应。前两个报文段不承载“有效载荷”,也就是不包含应用层数据;而第三个报文段可以承载有效载荷。
由于在这两台主机之间发送了3个报文段,所以这种连接建立过程常被称为三次握手(three-way handshake)

6)一旦建立一条TCP连接,两个应用进程之间就可以相互发送数据了。客户进程通过套接字(该进程之门)传递数据流。数据一旦通过该门,它就有客户中运行的TCP控制了。如下图所示,TCP将这些数据引导到该连接的发送缓存(send buffer)里,发送缓存是在三次握手初期设置的缓存之一。

7)首先介绍几个名词:

最大报文长度(Maximum Segment Size,MSS):指报文段里应用层数据的最大长度,而不是指包括TCP首部的TCP报文段的最大长度。个人理解如下图所示:

最大传输单元(Maximum Transmission Unit,MTU):本地发送主机发送的最大链路层帧长度。

TCP可以从缓存中取出并放入报文段中的数据数量受限于MSS,MSS通常由MTU来设置,该MSS要保证一个TCP报文段(当封装在一个IP数据报中)加上TCP/IP首部长度(通常是40字节)将适合单个链路层帧。以太网和PPP链路层协议都具有1500字节的MTU,因此,MSS的典型值为1460字节。

8)TCP连接的组成包括:一台主机上的缓存、变量和与进程连接的套接字,以及另一台主机的另一组缓存、变量和与进程连接的套接字。

5.2 TCP报文段结构

TCP报文段由首部字段和一个数据字段(包含一块应用数据)组成。

1)当TCP发送一个大文件时,TCP通常将该文件划分为长度为MSS的若干块(最后一块除外,它通常小于MSS)。

2)然而,交互式应用通常传送长度小于MSS的数据块。例如,对于像Telnet这样的远程登录应用,其TCP报文段的数据字段经常只有一个字节。由于TCP的首部一般是20字节(比UDP首部多12字节),所以Telnet发送的报文段也许只有21字节长。

3)TCP报文段结构如上图,其中首部包括:

①源端口号和目的端口号:被用于多路复用/分解来自或送到上层应用的数据。

②检验和字段(checksum field)

③32bits的序号字段(sequence number field)和32bits的确认号字段(acknowledgement number field):这些字段被TCP发送方和接收方用来实现可靠数据传输服务。

④16bits的接收窗口字段(receive window field):该字段用于流量控制(该字段用于指示接收方愿意接受的字节数量)。

⑤4bits的首部长度字段(header length field):字段指示了以32bits的字为单位的TCP首部的长度。由于TCP选项字段的原因,TCP首部的长度是可变的(通常,选项字段为空,所以TCP首部的典型长度就是20字节。)

⑥可选与变长的选项字段(options field):该字段用于发送方与接收方协商最大报文段长度(MSS)时,或在高速网络环境下用作窗口调节因子时使用。

⑦6bits的标志字段(flag field):

ACK比特:用于指示确认字段中的值是有效的,即该报文段包含一个对已被成功接收报文段的确认。
RST、SYN和FIN比特:用于连接建立和拆除。
PSH比特:该比特被设置时,就指接收方应立即将数据交给上层。
URG比特:用于指示报文段里存在着被发送端的上层实体置为“紧急”的数据。

⑧紧急数据指针字段(urgent data pointer):紧急数据的最后一个字节由16比特的紧急数据指针字段指出。当紧急数据存在并给出指向紧急数据尾的指针的时候,TCP必须通知接收端的上层实体。(在实践中,PSH、URG和紧急数据指针并没有使用。为了完整性,才提到这些字段。

序号和确认号

序号和确认号是TCP报文段首部中两个最重要的字段。这两个字段是TCP可靠传输服务的关键部分。

序号:

TCP把数据看成一个无结构、有序的字节流。因为序号是建立在传送的字节流之上,而不是建立在传送的报文段的序列之上。则一个报文段的序号(sequence number for a segment)是该报文段首字节的字节流编号。

假设主机A上的一个进程想通过一条TCP连接向主机B上的一个进程发送一个数据流。主机A中的TCP将隐式地对数据流中的每一个字节编号。假设数据流由一个500 000字节的文件组成,其MSS为1000字节,数据流的首字节编号为0。则TCP将为该数据流构建500个报文段,给第一个报文段分配序号为0,第二个报文段分配序号1000,第三个报文段分配序号2000,以此类推。每一个序号被填入到相应TCP报文段首部的序号字段中。

如果序号超过4 294 967 295怎么办?即超过5GB的数据如何分配序号?超过32位的存储了。

确认号:

TCP是全双工的,因此主机A向主机B发送数据的同时,也许也接收者来自主机B的数据(都是同一条TCP连接的一部分)。从主机B到达的每个报文段中都有一个序号用于从B流向A的数据,主机A填充进报文段的确认号是主机A期望从主机B收到的下一字节的序号。

举例,主机A已收到来自主机B的包含字节0~535的报文段,以及另一个包含字节900~1000的报文段,由于某种原因,主机A还没收到字节536~899的报文段。在这个例子中,主机A为了重新构建主机B的数据流,仍在等待字节536(和其后的字节)。因此,A到B的下一个报文段将在确认号字段中包含536.因为TCP只确认该流中至第一个丢字节为止的字节,所以TCP被称为提供累积确认(cumulative acknowledgment)。

当主机在一条TCP连接中收到失序报文段时该怎么办?TCP RFC并没有为此明确规定,而是由TCP的编程人员实现。他有两个基本的选择:①接收方立即丢弃失序报文段;②接收方保留失序的字节,并等待缺少的字节以填补该间隔(后一种选择对网络带宽而言更为有效,是实践中采用的方法)。

值得注意的是,对客户到服务器的数据的确认被装载在一个承载服务器到客户的数据的报文段中;这种确认被称为是被捎带(piggybacked)在服务器到客户的数据报文段中的。

5.3 往返时间的估计与超时

TCP如同rdt协议一样,它采用超时/重传机制来处理报文段的丢失问题。

1)超时间隔长度的设置?显然,超时时间间隔必须大于该连接的往返时间(RTT),即从一个报文段发出到它被确认的时间。

2)如何估计往返时间?

3)是否应该为所有未确认的报文段各设一个定时器?

估计往返时间

报文段的样本RTT(表示为SampleRTT)就是从某报文段被发出(即交给IP)到对该报文段的确认被收到之间的时间量。大多数TCP的实现仅在某个时刻做一次SampleRTT测量,而不是为每个发送的报文段测量一个SampleRTT.

//指数加权移动平均(Exponential Weighted Moving Average,EWMA)。
//推荐的a=0.25
EstimatedRTT = (1 – a) • EstimatedRTT + a • SampleRTT
//推荐的b=0.25
//DevRTT:RTT偏差,测量RTT的变化。
DevRTT = (1 – b) • DevRTT + b•| SampleRTT – EstimatedRTT |
设置和管理重传超时间隔

超时间隔应该大于等于EstimatedRTT,否则将造成不必要的重传。但超时时间间隔也不能比EstimatedRTT大太多,否则当报文段丢失时,TCP不能很快地重传该报文段,导致数据传输时延大。

//推荐TimeoutInterval值为1秒。超时后,TimeoutInterval值将加倍。
//一旦报文段收到并更新EstimatedRTT后,TimeoutInterval就使用下式
TimeoutInterval = EstimatedRTT + 4 • DevRTT

1)TCP通过使用肯定确认与定时器来提供可靠数据传输。TCP确认正确接收到的数据,而当认为报文段或其确认报文丢失或受损后,TCP会重传这些报文段。

2)TCP使用流水线,使得发送方在任意时刻都可以有多个已发出但还未确认的报文段存在。一个发送方具有的未被确认报文段的确切个数是由TCP的流量控制和拥塞控制机制决定的。

3.5.4 可靠数据传输

对于IP服务,数据报能够溢出路由器缓存而永远不能到达目的地,数据报也可能乱序到达,而且数据报中的比特可能损坏。TCP在IP不可靠的尽力而为服务之上创建一种可靠数据传输服务。TCP的可靠数据传输服务确保了一个进程从其接收缓存中读取数据流是无损坏、无间隔、非冗余和按序的数据流。

接下来讨论:

1)简化版本:发送方只用超时技术来恢复报文段丢失。

2)全面版本:除了使用超时机制外,还使用冗余确认技术。

简化版本描述:TCP发送方有3个与发送和重传有关的主要事件(①从上层应用程序接收数据;②定时器超时;③收到ACK;)

/* Assume sender is not constrained by TCP flow or congestion control, that data from above is less than MSS in size, and that data transfer is in one direction only. */
NextSeqNum=InitialSeqNumber
SendBase=InitialSeqNumber

loop (forever) {
    switch(event)

        event: data received from application above
            create TCP segment with sequence number NextSeqNum
            if (timer currently not running)
                start timer
            pass segment to IP
            NextSeqNum=NextSeqNum+length(data)
            break;

        event: timer timeout
            retransmit not-yet-acknowledged segment with
                smallest sequence number
            start timer
            break;

        event: ACK received, with ACK field value of y
            if (y > SendBase) {
                SendBase=y
                if (there are currently any not-yet-acknowledged segments)
                    start timer
            }
        break;
} /* end of loop forever */

1)TCP从应用程序接收数据,将数据封装在一个报文段中,并把该报文段交给IP。(①注意到每一个报文段都包含一个序号,这个序号就是该报文段第一个数据字节的字节流编号。②如果定时器还没有为某些其他报文段而运行,则当报文段被传给IP时,TCP就启动该定时器。)

2)超时:TCP通过重传引起超时的报文段来响应超时事件。

3)来自接收方的确认报文段(ACK)的到达:TCP将ACK的值y与它的变量SendBase(是最早未被确认的字节序号)进行比较。TCP采用累积确认,所以y确认了字节编号在y之前的所有字节都已经收到。如果y > SenfBase,则该ACK是在确认一个或多个先前未被确认的报文段。因此,发送方更新它的SendBase变量。

一些情况

情况一:

情况二:

情况三:

超时间隔加倍

大多数TCP实现中所做的一些修改:TCP重传具有最小序号的还未被确认的报文段。只是每次TCP重传时都会将下一次的超时间隔设为先前值的两倍,而不是从EstimatedRTT和DevRTT推算出的值。然而,每当定时器在另两个事件(即收到上层应用数据或收到ACK)中的任意一个启动,TimeoutInterval由最近的EstimatedRTT和DevRTT推算得到。

优点:这种修改提供了一个形式受限的拥塞控制。定时器过期很有可能是由网络拥塞引起的,即太多的分组到达源与目的地之间路径上一台(或多台)路由器的队列中,造成分组丢失或长时间的排队时延。在拥塞的时候,如果源持续重传分组,会使拥塞更加严重。因此,TCP使用更好的方法,每个发送方的重传都是经过越来越长的时间间隔后进行的。

快速重传

问题:超时触发重传存在的问题是超时周期可能相对较长,当一个报文段丢失时,这种长超时周期迫使发送方延迟重传丢失的分组,因而增加了端到端时延。

解决办法:冗余ACK(duplicate ACK):就是再次确认某个报文段的ACK,而发送方先前已经收到对该报文段的确认。(通过下面理解:发送方通常在超时事件发生之前通过注意所谓冗余ACK来较好地检测到丢包情况。)

TCP接收方的ACK生成策略:

因为发送方经常一个接一个地发送大量的报文段,如果一个报文段丢失,就很可能引起许多一个接一个的冗余ACK。如果TCP发送方接收到对相同数据的3个冗余ACK,它把这当做一种暗示,说明跟在这个已被确认3次的报文段之后的报文段已经丢失(为何是3个冗余ACK?)。一旦受到3个冗余ACK,TCP就执行快速重传(fast retransmit),即在该报文段的定时器过期之前重传丢失的报文段。

快速重传的TCP,其ACK收到事件:

event: ACK received, with ACK field value of y
    if (y > SendBase) {
        SendBase=y
        if (there are currently any not yet acknowledged segments)
            start timer
        }
    else { /* a duplicate ACK for already ACKed segment */
        increment number of duplicate ACKs received for y
        if (number of duplicate ACKS received for y==3)
            /* TCP fast retransmit */
            resend segment with sequence number y
        }
    break;

是回退N步还是选择重传

TCP是一个GBN协议还是一个SR协议?

1)TCP确认是累积式地、正确地接收,但是失序的报文段是不会被接收方逐个确认的。TCP发送方仅需维持已发送过但未被确认的字节的最小序号(SendBase)和下一个要发送的字节的序号(NextSeqNum)。这个意义下,TCP看起来更像一个GBN风格的协议。

2)但是TCP和GBN协议之间有着一些显著的区别,许多TCP实现会将正确接收但失序的报文段缓存起来。考虑一下当发送方发送一组报文段1、2、…N的序列时,所有的报文段都是在接收方按序无差错的情况下到达的。进一步假设,对包n小于N的确认报文丢失了,但是其余的N-1确认报文在它们各自的超时之前到达了发送端。在这个例子中,GBN不仅会重新传输数据包n,还会传送所有的后续分组,n+1 n+2,…N。另一方面,TCP将重传至多一个报文段,即报文段n。此外,如果报文段n+1的确认报文在报文段n超时之前到达。TCP甚至不会重新传输段n。

3)TCP提出的一种修改意见是所谓的选择确认(selective acknowledgment)[RFC2018],它允许TCP接收方有选择地确认失序报文段,而不是累积地确认最后一个正确接收的有序报文段。当该机制与选择重传机制结合起来使用时(即跳过重传那些已被接收方选择性地确认过的报文段),TCP看起来像SR协议。因此,TCP的差错恢复机制最后被分类为GBN协议与SR协议的混合体。

5.5 流量控制

一条TCP连接的每一侧主机都为该连接设置了接收缓存。当该TCP连接收到正确、按序的字节后,他就将数据放入到接收缓存。(注意:相关联的进程会从该缓存中读取数据,但不是数据刚一到就立即读取。)

TCP为应用程序提供了流量控制服务(flow-control-service)以消除发送方使接收方缓存溢出的可能性。

流量控制服务(flow-control-service):是一个速度匹配服务,即发送方的发送速率与接收方应用程序的读取速率相匹配。

拥塞控制(congestion control):TCP发送方可能因为IP网络的拥塞而被抑制。

注意:本节假设TCP接收方丢弃失序的报文段。

接收窗口(receive window):用于给发送方一个指示:该接收方还有多少可用的缓存空间。TCP通过让发送方维护一个称为接收窗口的变量来控制流量的控制。

因为TCP是全双工通信,在连接两端的发送方都各自维护一个接收窗口。

假设主机A通过一条TCP连接向主机B发送一个大文件。主机B为连接分配了一个接收缓存RecvBuffer表示其大小。

//定义以下变量
• LastByteRead: the number of the last byte in the data stream read from the buffer by the application process in B
• LastByteRcvd: the number of the last byte in the data stream that has arrived from the network and has been placed in the receive buffer at B
//由于TCP不允许已分配缓存溢出,下式必须成立:
LastByteRcvd – LastByteRead ≤ RcvBuffer
//接收窗口用rwnd表示,根据缓存可用空间数量来设置:
rwnd = RcvBuffer – [LastByteRcvd – LastByteRead]

由于该空间是随着时间变化的,所以rwnd是动态的,rwnd也称为滑动窗口。

1)连接是如何使用变量rwnd提供流量控制服务?主机B通过把当前的rwnd值放入它发送给主机A的报文段接收窗口字段中,通知主机A它在该连接的缓存中还有多少可用空间。

开始时,主机B设定rwnd = RecvBuffer。主机A轮流跟踪两个变量LastByteSent和LastByteAcked。(LastByteSent-LastByteAcked:表示主机A发送到连接中但未被确认的数据量)。通过将未确认的数据量控制在rwnd以内,就可以保证主机A不会使主机B的接收缓存溢出。

因此,主机A在整个生命周期需保证:LastByteSent – LastByteAcked ≤ rwnd

2)这个方案有一个小技术问题。 假设主机B的接收缓冲区已满,使得rwnd = 0。在将rwnd = 0通知给主机A,也假设B没有什么可以发送到A。现在考虑发生什么情况,当B中的应用进程清空缓冲区时,TCP不会向主机A发送新的带有rwnd新值的新报文段; 实际上,TCP只有它有数据或者有确认要发送时才会发送保文段向主机A。因此,主机A不知道Host B的接收缓冲区已有新的空间了。即主机A被阻塞,并且不能传输更多的数据! 为了解决这个问题,TCP规范要求:当B的接收窗口为零时,主机A继续发送一个只有1个字节数据的报文段。 这些报文段将会被接收器确认。最终缓冲区将开始清空,并且确认报文里将包含一个非0的rwnd值。

5.6 TCP连接管理

本节关注建立和拆除一条TCP连接。即三次握手,四次挥手。

建立连接

TCP连接的建立会显著地增加人们感受到的时延。客户中的TCP会用以下方式与服务器中的TCP建立一条

TCP连接:

TCP SYN报文段

1)第一步:客户端TCP首先向服务器端的TCP发送一个特殊的TCP报文段(TCP SYN报文段:该报文段不包含应用层数据,但在报文段的首部中的一个标志位SYN被置为1.)。另外,客户会随机选择一个初始序号(client_isn),并将次编号放置与该起始的TCP SYN报文段的序号字段中。该报文段会被封装在一个IP数据报中,并发送给服务器。

SYNACK报文段

2)第二步:一旦包含TCP SYN报文段的IP数据报到达服务器主机(假定它的确达到了),服务器会从该数据报中提取出TCP SYN报文段,为TCP连接分配TCP缓存和变量,并向该客户TCP发送允许连接的报文段(分配的这些缓存和变量,使得TCP易于受到SYN洪泛的拒绝服务攻击),这个允许连接的报文段(SYNACK报文段:该首部有3个重要信息①SYN置为1;②确认号字段被置为client_isn+1;③服务器选择自己的初始序号server_isn,并将其放在TCP报文段首部的序号字段中。)不包含应用层数据。

3)在收到SYNACK报文段后,客户也要给该连接分配缓存和变量。客户主机则向服务器发送另外一个报文段;这最后一个报文段对服务器的允许连接的报文段进行了确认(首部中:①确认字段为server_isn+1;②序号字段为client_isn+1;③SYN比特置为0)。该三次握手的第三个阶段可以在报文段负载中携带客户到服务器的数据。

在以后的每一个报文段中,SYN比特都被置为0;这种连接创建过程被称为3次握手(three-way handshake)。

TCP拆除:

参与一条TCP连接的两个进程中的任意一个都能终止该连接。当连接结束后,主机中的“资源(缓存和变量)”将被释放。

假设某客户打算关闭连接:

1)客户应用进程发送一个关闭连接命令:客户TCP向服务器进程发送一个特许TCP报文段(首部的标志位FIN置为1)

2)当服务器接收到该报文段后,就向发送方发送一个确认报文段。

3)服务器发送它自己的终止报文段,其FIN比特置为1.

4)客户对这个服务器的终止报文段进行确认。(此时,两个主机用于连接的所有资源都被释放了。)

客户TCP状态图

1)客户TCP开始处于CLOSED状态。

客户应用程序发起一个新的连接,则客户TCP向服务器中的TCP发送一个SYN报文段

2)发送过SYN报文段后,客户TCP进入了SYN_SENT状态。

接着,等待来自服务器TCP的对客户所发报文段进行确认且SYN比特被置为1的一个报文段(SYNACK报文段)

3)收到SYNACK报文段之后,客户TCP进入ESTABLISHED(已建立)状态。

当处在ESTABLISHED状态时,TCP客户就能发送和接收包含有效载荷数据(即应用层产生的数据)的TCP报文段了。

4)假设客户要决定关闭该连接,这引起客户TCP发送一个带有FIN比特被置为1的TCP报文段,进入FIN_WAIT_1状态。

客户等待来自服务器的带有确认的TCP报文段。

5)收到上述报文段后,客户TCP进入FIN_WAIT_2状态。

客户等待来自服务器的FIN比特置为1的另一个报文段。

6)收到上述报文段后,客户TCP对服务器发送确认报文段进行确认,并进入TIME_WAIT状态。

假设ACK丢失,TIME_WAIT状态使TCP客户重传最后的确认报文。在TIME_WAIT状态中所消耗的时间是与具体实现有关的,而典型值是30s,1min,或2min。经过等待后,连接就正式关闭,客户端所有资源(包括端口号)将被释放。

服务器TCP状态图

下面考虑一台主机接收到一个TCP报文段,其端口号或源IP地址与该主机上进行中的套接字都不匹配。则该主机将向源发送一个特殊重置报文:该报文段将RST标志位置为1.当一台主机接收一个UDP分组,它的目的端口与进行中的UDP套接字不匹配,该主机发送一个特殊的ICMP数据报。

nmap是一个功能强大的工具,该工具不仅能“侦查”打开的TCP端口,也能“侦查”UDP端口,还能侦查防火墙及其配置,甚至能侦查应用程序的版本和操作系统,大多数都能通过操作TCP连接管理报文段完成。可以从http://www.nmap.org中下载nmap。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值