TCP协议详解(下)



TCP协议详解

TCP状态转移

TCP连接的任意一端在任一时刻都处于某种状态,当前状态可以通过netstat命令查看,这里我们主要讨论TCP连接葱白建立到关闭的整个过程中通信两端状态的变化。如图是TCP状态转移过程。

图中,粗虚线表示典型的服务器连接的状态转移;粗实线显示典型的客户端连接的状态转移。

TCP状态转移总图

服务器转移过程,这里我们说的连接状态指定是该连接的服务器状态。

服务器通过listen系统调用进入LISTEN状态,被动等待客户端连接,因此执行的是所谓的被动打开。服务器一旦监听到某个连接请求(收到同步报文段),就将该连接放入内核等待队列中,并想客户端发送SYN标志的确认报文段。此时该连接处于SYN_RCVD状态。如果服务器成功接收到客户端发送的确认报文段,则该连接转移到ESTABLISHED状态。ESTABLISHED状态是连接双方能够进行双向数据传输的状态。

当客户端主动关闭连接时(通过close或shutdown系统调用想服务器发送结束报文段),服务器通过返回确认报文段使连接进入CLOSE_WAIT状态。这个状态的含义很明确:等待服务器应用程序关闭连接。通常,服务器检测到客户端关闭连接后,也会立即给客户端发送一个结束报文段来关闭连接。这将使连接转移到LAST_ACK状态,以等待客户端对结束报文段的最后一次确认。一旦完成确认,连接就侧地关闭。

客户端状态转移过程,此时我们所说的连接状态都是指该连接的客户端状态

客户端通过connect系统调用主动与服务器连接。connect系统调用首先给服务器发送一个同步报文段,使连接转移到SYN_SENT状态。此后,connect系统调用可能因为如下两个原因失败返回:

  1. 如果connect连接的目标不存在(未被任何进程监听),或者改端口仍被处于TIME_WAIT状态的连接所占用,则服务器将给客户端发送一个复位报文段,connect调用失败。
  2. 如果目标端口存在,但connect在超时时间内未收到服务器的确认报文段,则connect调用失败。

connect调用失败将使连接立即返回到初始CLOSED状态。如果客户端成功接收到服务器的同步报文段和确认,则connect调用成功,连接转移至ESTAVLISHED状态。

当客户端执行主动关闭时,它将向服务器发送一个结束报文段,同时连接进入FIN_WAIT_1状态。若此时客户端收到服务器专门用于确认目的的确认报文段,则连接转移至FIN_WAIT_2状态。当客户端处于FIN_WAIT_2状态时,服务器处于CLOSE_WAIT状态,这一对状态可能发生半关闭状态。此时如果服务器关闭连接(发送结束报文段),则客户端将给与确认并进入TIME_WAIT状态。图中还给出了客户端从FIN_WAIT_1状态直接进入TIME_WAIT状态的一跳路线,前提是处于FIN_WAIT_1的客户端直接收到带确认信息的结束报文段。

连接停留在FIN_WAIT_2状态可能发生:客户端执行半关闭后,未等待服务器关闭连接就强行退出了。此时客户端连接由内核接管,称之为孤儿连接。Linux为了防止故而连接长时间存留在内核中,定义了两个内核变量:/pro/sys/net/ipv4/tcp_max_orphans和/proc/sys/net/ipv4/tcp_fin_timeout。前者指定内核能接管的孤儿连接数目,后者指定孤儿连接在内核中的生存时间。

下图是客户端和服务器的状态转移图

TIME_WAIT状态

客户端连接在在收到服务器的结束报文段之后,并没有直接进入CLOSED状态,而是转移到TIME_WAIT状态。在这个状态,客户端连接要等待一段长为2MSL(Maximum
Segment Life)的时间,才能完全关闭。MSL是TCP报文段在网络中的最大生存时间、

TIME_WAIT状态存在的原因有两点:

  1. 可靠地种植TCP连接
  2. 保证让迟来的TCP报文段有足够的时间被识别并丢弃

第一个原因如上图中的确认报文段被丢弃,那么服务器重发结束报文段。因此客户端需要停留在某个状态以处理重复收到的结束报文段。

第二个原因是在Linux上,一个TCP端口不能被同时打开多次,当一个TCP连接处于TIME_WAIT状态时,我们将无法立即使用该连接占用的端口来建立一个新连接。否则,应用程序能够立即建立一个和刚才关闭的连接相似的连接,这个新连接可能接受原连接写阿迪的TCP报文段,这显然不合理。

复位报文段

在某些情况下,TCP连接的一端会向另一端发送携带RST标志恩德报文段,即复位报文段,以通知对方关闭连接或重新建立连接。产生复位报文段主要有以下3种情况:

  1. 访问不能存在的端口或
  2. 异常终止连接

    TCP提供了异常终止一个连接的方法,即给对方发送一个复位报文段。一旦发送了复位报文段,发送端所有排队等待发送的数据都将被丢弃。

  3. 处理板打开连接

服务器(或客户端)关闭或异常终止了连接,而对方没有接收到结束报文段,此时,客户端(或服务器)还维持着原来的连接,而服务器(或客户端)即使重启,也已经没有该连接的任何信息了。我们将这种状态成为半打开状态,处于这种状态的连接称为半打开连接。如果客户端(或服务器)网处于半打开状态的连接写入数据,则对方将回应一个复位报文段。

TCP交互数据流和TCP成块数据流

TCP报文段所携带的用用程序数据按照长度分为两种:交互数据和成块数据。交互数据仅包含很少的字节,使用交互数据的应用程序对实时性要求更高,比如telnet、ssh等。成块数据的长度则通常为TCP报文允许的最大数据长度,使用成块数据的应用程序对成熟效率要求较高,比如ftp。

对于TCP成块数据流,当传输大量大块数据的时候,发送方会连续发送多个TCP报文段,接收方可以一次确认所有这些报文段。

带外数据

有些传输层协议具有带外(OutOf
Band, OOB)数据的概念,用于迅速通告对方本端发生的重要事件。因此,带外数据比普通数据有更高的优先级,它也应该是立即被发送,二不论发送缓冲区钟波是否有排队等待发送的普通数据。带外数据的传输可以使用一条独立的传输层链接,也可以映射到传输普通数据的连接,

UDP没有实现带外数据传输,TCP也没有真正的带外数据,不过TCP的紧急方式利用传输普通数据的连接来传输紧急数据。这种紧急数据的含义和带外数据类似,因此这里讲TCP紧急数据称为带外数据。

TCP发送带外数据的过程。假设一个进程已经往某个TCP连接的发送端缓冲区写入N字节的普通数据,并等待期发送。在数据被发送前,该进程又向这个链接写入了3字节的带外数据“abc”。此时,待发送的TCP报文段的头部被设置URG标志,并且紧急指针被设置为指向最后一个带外数据的下一个字节,如下图所示:

由上图可见,发送端一次发送的多字节的带外数据中只有最后一字节被当做带外数据(字母c),而其他数据(字母a和b)被当成了普通数据。如果TCP模块以多个TCP报文段来发送上图所示TCP缓冲区中的内容,则每个TCP报文段都将设置URG标志,并且它们的紧急指针指向同一个位置(数据流中带外数据的下一个位置),但只有一个TCP保温真正携带带外数据。

TCO接收带外数据时,TCP接收端只有在接受奥紧急指针标志时才检查紧急指针,然后根据紧急指针所知的位置确定带外数据的位置,并将它读入一个特殊的缓冲中。这个缓冲只有1个字节,成为带外缓冲。如果上层应用程序没有及时将带外数据从带外缓冲中读出,则后续的带外数据将覆盖它。

除了前面讨论的接收带外数据的默认方式外,如果我们给TCP连接设置了SO_OOBINLINE选项,则带外数据将和普通数据一样被TCP模块放在TCP缓冲区中,此时应用程序需要向读取普通数据一样来读取带外数据。

TCP超时重传

TCP必须能够重传超时时间内未收到确认的TCP报文段。为此,TCP模块为每个TCP报文段都维护一个重传定时器,该定时器在TCP报文段第一次被发送时启动。如果超时时间内未收到接收方的应答,TCP模块将重传TCP报文段并重置定时器。至于下次重传的超时时间如何选择,以及最多执行多少次重传,就是TCP的重传策略。

下面是一种重传策略:

指数退避原则,则在超时后每次会增加超时时间,基本为上次的二倍,达到64s后保持为64S。一直传送系统设置的最大次数,超过最大次数后关闭连接。

拥塞控制

TCP模块还有一个重要的任务,就是提高网络利用率,降低丢包率,并保证网络资源对每条数据流的公平性。这就是所谓的拥塞控制。

拥塞控制的最终受控变量是发送端向网络一次连续写入(收到其中第一个数据的确认之前)的数据量,我们称为SWND(Send
Window,发送窗口)。不过,发送端最终以TCP报文段来发送数据,所以SWND限定了发送端能连续发送的TCP报文段数量。这些TCP报文段的最大长度(仅指数据部分)称为SMSS(Sender
Maximum Segment Size,发送者最大段大小),其值一般等于MSS。

发送端需要合理地选择SWND的大小。如果SWND太小,会引起明显的网络延迟;反之,如果SWND太大,则容易导致网络拥塞。前文提到,接收方可通过其接收通告窗口(RWND)来控制发送端的SWND。但这显然不够,所以发送端引入了一个称为拥塞窗口(Congestion
Window,CWND)的状态变量。实际的SWND值是RWND和CWND中的较小者。

快速重传和快速恢复

TCP连接建立好之后,CWND将被设置成初始值IW(InitialWindow),其大小为2~4个SMSS。

此时发送端最多能发送IW字节的数据。此后发送端每收到接收端的一个确认,其CWND就按照式(3-1)增加:

CWND+=min(N,SMSS)(3-1)

其中N是此次确认中包含的之前未被确认的字节数。这样一来,CWND将按照指数形式扩大,这就是所谓的慢启动。慢启动算法的理由是,TCP模块刚开始发送数据时并不知道网络的实际情况,需要用一种试探的方式平滑地增加CWND的大小。

但是如果不施加其他手段,慢启动必然使得CWND很快膨胀(可见慢启动其实不慢)并最终导致网络拥塞。因此TCP拥塞控制中定义了另一个重要的状态变量:慢启动门限(slow
start threshold size,ssthresh)。当CWND的大小超过该值时,TCP拥塞控制将进入拥塞避免阶段。

拥塞避免算法使得CWND按照线性方式增加,从而减缓其扩大。

每个RTT时间内按照式(3-1)计算新的CWND,而不论该RTT时间内发送端收到多少个确认。

每收到一个对新数据的确认报文段,就按照式(3-2)来更新CWND。

CWND+=SMSS*SMSS/CWND (3-2)

以上我们讨论了发送端在未检测到拥塞时所采用的积极避免拥塞的方法。接下来介绍拥塞发生时(可能发生在慢启动阶段或者拥塞避免阶段)拥塞控制的行为。不过我们先要搞清楚发送端是如何判断拥塞已经发生的。发送端判断拥塞发生的依据有如下两个:

1.传输超时,或者说TCP重传定时器溢出。

2.接收到重复的确认报文段。

拥塞控制对这两种情况有不同的处理方式。对第一种情况仍然使用慢启动和拥塞避免。对第二种情况则使用快速重传和快速恢复(如果是真的发生拥塞的话),这种情况将在后面讨论。注意,第二种情况如果发生在重传定时器溢出之后,则也被拥塞控制当成第一种情况来对待。

如果发送端检测到拥塞发生是由于传输超时,即上述第一种情况,那么它将执行重传并做如下调整:

ssthresh=max(FlightSize/2,2*SMSS)(3-3)

CWMD<=SMSS

其中FlightSize是已经发送但未收到确认的字节数。这样调整之后,CWMD将小于SMSS,那么也必然小于新的慢启动门限值ssthresh(因为根据式(3-3),它一定不小于SMSS的2倍),故而拥塞控制再次进入慢启动阶段。

快速重传和快速恢复

在很多情况下,发送端都可能接收到重复的确认报文段,比如TCP报文段丢失,或者接收端收到乱序TCP报文段并重排之等。拥塞控制算法需要判断当收到重复的确认报文段时,网络是否真的发生了拥塞,或者说TCP报文段是否真的丢失了。具体做法是:发送端如果连续收到3个重复的确认报文段,就认为是拥塞发生了。然后它启用快速重传和快速恢复算法来处理拥塞,过程如下:

1)当收到第3个重复的确认报文段时,按照式(3-3)计算ssthresh,然后立即重传丢失的报文段,并按照式(3-4)设置CWND。

CWND=ssthresh+3*SMSS(3-4)

2)每次收到1个重复的确认时,设置CWND=CWND+SMSS。此时发送端可以发送新的TCP报文段(如果新的CWND允许的话)。

3)当收到新数据的确认时,设置CWND=ssthresh(ssthresh是新的慢启动门限值,由第一步计算得到)。

快速重传和快速恢复完成之后,拥塞控制将恢复到拥塞避免阶段,这一点由第3步操作可得知。

参考Linux高性能服务器编程

转载请注明出处,谢谢~~

TCP协议详解(下),布布扣,bubuko.com

时间: 2024-10-12 18:59:35

TCP协议详解(下)的相关文章

TCP协议详解即实例分析

 TCP协议详解 3.1 TCP服务的特点 TCP协议相对于UDP协议的特点是面向连接.字节流和可靠传输. 使用TCP协议通信的双方必须先建立链接,然后才能开始数据的读写.双方都必须为该链接分配必要的内核资源,以还礼链接状态和连接上数据的传输.TCP链接是全双工的,即双方的数据读写可以通过一个连接进行.完成数据交换之后,通信双方都必须断开连接以释放系统资源. TCP协议的这种连接是一对一的,所以基于广播和多播(目标是多个主机地址)的应用程序不能使用TCP服务.而无连接协议UDP则非常适合于广

TCP协议详解(理论篇)

TCP协议详解(理论篇) 1.    与UDP不同的是,TCP提供了一种面向连接的.可靠的字节流服务.面向连接比较好理解,就是连接双方在通信前需要预先建立一条连接,这犹如实际生活中的打电话.助于可靠性,TCP协议中涉及了诸多规则来保障通信链路的可靠性,总结起来,主要有以下几点: (1)应用数据分割成TCP认为最适合发送的数据块.这部分是通过"MSS"(最大数据包长度)选项来控制的,通常这种机制也被称为一种协商机制,MSS规定了TCP传往另一端的最大数据块的长度.值得注意的是,MSS只能

44 TCP 协议详解

44 TCP 协议详解 TCP 协议 传输控制协议, Transmission Control Protocol,其功能包括:传输:控制 传输包括:建立连接.关闭连接.保证可靠 建立连接:三次握手 三次握手(Three-Way Handshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立.在socket编程中,这一过程由客户端执行connect来触发,整个流程如下图所示: (1)第一次握手:Client将标志位SYN置为1,随机产生一个值se

第一章、TCP协议详解

TCP/IP协议包含众多协议,本章,我们介绍几个相关协议:ICMP协议,ARP协议,DNS协议,学习他们对于理解网络通信很有帮助. 一.TCP/IP协议族体系结构以及主要协议: TCP/IP协议从下到上分四层:数据链路层,网络层,传输层,应用层. 应用层 ping OSPF DNS 用户空间 传输层 TCP   UDP 网络层 ICMP     IP    内核空间 数据链路层 ARP data-link RARP 1.(1)数据链路层:实现了网卡接口的网络驱动程序,以处理数据在物理媒介(以太网

TCP协议详解---上

TCP头格式 注意以下几点: TCP的包是没有IP地址的,那是IP层上的事.但是有源端口和目标端口. 一个TCP连接需要四个元组来表示是同一个连接(src_ip, src_port, dst_ip, dst_port)准确说是五元组,还有一个是协议.但因为这里只是说TCP协议,所以,这里我只说四元组. 注意上图中的四个非常重要的东西: Sequence Number是包的序号,用来解决网络包乱序(reordering)问题. Acknowledgement Number就是ACK——用于确认收到

【TCP协议详解】

为什么会有TCP/IP协议 在世界上各地,各种各样的电脑运行着各自不同的操作系统为大家服务,这些电脑在表达同一种信息的时候所使用的方法是千差万别.就好像圣经中上帝打乱了各地人的口音,让他们无法合作一样.计算机使用者意识到,计算机只是单兵作战并不会发挥太大的作用.只有把它们联合起来,电脑才会发挥出它最大的潜力.于是人们就想方设法的用电线把电脑连接到了一起. 但是简单的连到一起是远远不够的,就好像语言不同的两个人互相见了面,完全不能交流信息.因而他们需要定义一些共通的东西来进行交流,TCP/IP就是

TCP协议详解(TCP建立连接与断开连接)

TCP是面向连接的.可靠的进程到进程通信的协议.它提供的是全双工(双向可传输)的服务,每个TCP都有发送缓存和接受缓存,用来临时存储数据. 1.TCP报文段:TCP把若干个字节构成一个分组,称为报文段(segment).TCP报文段封装在IP数据报中,TCP报文段的首部格式如下图所示: 首部长度为20~60个字节,一下是各个字段的含义:①:源端口号:它是16位字段,为发送发进程对应的端口号:②:目标端口号:它是16位字段,对应的是接收端的进程,接收端收到数据段后,根据这个端口号来确定把数据送给哪

TCP协议详解

TCP协议   传输控制协议 Transmission Control Protocal 功能点两点: 1.一个是传输功能:主要工作是建立连接和关闭连接 2.另一个是控制功能:主要工作是保证传输的可靠 建立连接的过程:三次握手 1.给对方拨号 2.接听,喂,你好,请问你哪位 3.我是强子 关闭连接过程:四次挥手 保证可靠 详细介绍三次握手过程: 第一次握手:客户端发送SYN包至服务器,并进入SYN_SENT状态,等待服务器确认 第二次握手:服务器收到客户端的SYN包,发送一个ACK,同时发送自己

【计算机网络】TCP协议详解

常见问题 Q1. TCP报文头结构多大? Q2. TCP为何采用三次握手来建立连接,若采用二次握手可以吗,请说明原因? Q3. TCP为何采用四次挥手来释放连接? TCP协议 首先,我们需要知道TCP在网络OSI的七层模型中的第四层——传输层(Transport),IP在第三层——网络层(Network),ARP在第二层——(Data Link),在第二层上的数据,我们叫帧(Frame),在第三层上的数据叫包(Packet),第四层的数据叫报文段(Segment). 1. TCP报文头结构 首先