TCPIPChap171819TCP

来源:互联网 发布:光伏智能软件 编辑:程序博客网 时间:2024/04/30 08:05
 

TCP总览

一、TCP特性

TCP通过以下特点来保证其可靠性:

(1)       应用数据被分割成T C P认为最适合发送的数据块。这和U D P完全不同,应用程序产生的数据报长度将保持不变(应用层数据直接封装成一个数据报)。由T C P传递给I P的信息单位称为报文段或段(s e g m e nt)。

(2)       当T C P发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。

(3)       当T C P收到发自T C P连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒。

(4)       T C P将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错, T C P将丢弃这个报文段和不确认收到此报文段(希望发端超时并重发)。

(5)       既然T C P报文段作为I P数据报来传输,而I P数据报的到达可能会失序,因此

T C P报文段的到达也可能会失序。如果必要, T C P将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。

(6)  既然I P数据报会发生重复, T C P的接收端必须丢弃重复的数据。

(7)  T C P还能提供流量控制。T C P连接的每一方都有固定大小的缓冲空间。T C P的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。

(8)  两个应用程序通过T C P连接交换8 bit字节构成的字节流。T C P不在字节流中插入记录标识符。我们将这称为字节流服务( byte stream service)。如果一方的应用程序先传1 0字节,又传2 0字节,再传5 0字节,连接的另一方将无法了解发方每次发送了多少字节。收方可以分4次接收这8 0个字节,每次接收2 0字节。一端将字节流放到T C P连接上,同样的字节流将出现在T C P连接的另一端。

(9)  T C P对字节流的内容不作任何解释。T C P不知道传输的数据字节流是二进制数据,还是A S C I I字符、E B C D I C字符或者其他类型数据。对字节流的解释由T C P连接双方的应用层解释。、

 

二、TCP包格式

TCP包格式如下:

TCP首部如果不计选项字段,通常是20个字节长度,格式如下:

(1)       Port/IP/Socket

每个T C P段都包含源端和目的端的端口号,用于寻找发端和收端应用进程。这两个值加上I P首部中的源端I P地址和目的端I P地址唯一确定一个T C P连接。

每个T C P段都包含源端和目的端的端口号,用于寻找发端和收端应用进程。这两个值加上I P首部中的源端插口对(s o c k e t p a i r)(包含客户I P地址、客户端口号、服务器I P地址和服务器端口号的四元组)可唯一确定互联网络中每个T C P连接的双方。I P地址和目的端I P地址唯一确定一个T C P连接。

(2)sequence ID(序号)

T C P为应用层提供全双工服务。这意味数据能在两个方向上独立地进行传输。因此,连接的每一端必须保持每个方向上的传输数据序号。

序号用来标识从T C P发端向T C P收端发送的数据字节流,它表示在这个报文段中的的第一个数据字节的位置序号。

当建立一个新的连接时, S Y N标志变1。序号字段包含由这个主机选择的该连接的初始序号I S N(Initial Sequence Number)(随时间随机变化的一个数,避免TCP伪装)。该主机要发送数据的第一个字节序号为这个I S N加1,因为S Y N标志消耗了一个序号

(3)ACK sequence ID(确认序号)

既然每个传输的字节都被计数,确认序号包含发送确认的一端所期望收到的下一个序号。因此,确认序号应当是上次已成功收到数据字节序号加1。只有A C K标志(下面介绍)为1时确认序号字段才有效。

(4)首部长度

4字节的个数,首部最多有60个字节,因此首部长度最大为15.

(5)标志位

U R G 紧急指针( u rgent pointer)有效(见2 0 . 8节)。

A C K 确认序号有效。

P S H 接收方应该尽快将这个报文段交给应用层。

R S T 重建连接。

S Y N 同步序号用来发起一个连接。这个标志和下一个标志将在第1 8章介绍。

F I N 发端完成发送任务。

(6)窗口大小

T C P的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个16 bit字段,

因而窗口大小最大为6 5 5 3 5字节。

(7)紧急指针

只有当U R G标志置1时紧急指针才有效。紧急指针是一个正的偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。T C P的紧急方式是发送端向另一端发送紧急数据的一种方式。

 

 

三、创建连接流程

1) 请求端(通常称为客户)发送一个S Y N段指明客户打算连接的服务器的端口,以及初始序号(I S N,在这个例子中为1 4 1 5 5 3 1 5 2 1)。这个S Y N段为报文段1。

2) 服务器发回包含服务器的初始序号的S Y N报文段(报文段2)作为应答。同时,将确认序号设置为客户的I S N加1以对客户的S Y N报文段进行确认。一个S Y N将占用一个序号。

3) 客户必须将确认序号设置为服务器的I S N加1以对服务器的S Y N报文段进行确认(报文段3)。

发送第一个S Y N的一端将执行主动打开( active open)。接收这个S Y N并发回下一个S Y N的另一端执行被动打开( passive open)。

 

 

四、终止连接流程

(1)客户端应用层,关闭socket,客户端向服务端发送一个FIN(主动关闭 active clise)

(2)服务端收到FIN后,将回一个ACK给客户端(被动关闭 passive close),同时,将向应用层传递一个文件结束符(read返回-1)【客户端到服务端的半连接关闭了】

(3)服务端在read返回-1时,向客户端发送FIN(主动关闭)

(4)客户端在收到FIN后,向服务端发送ACK(被动关闭)【服务端到客户端的半连接关闭了】

注意几点:

TCP连接是全双工

(1)       建立一个连接需要三次握手,而终止一个连接要经过4次握手。这由T C P的半关闭(h a l f -c l o s e)造成的。既然一个T C P连接是全双工(即数据在两个方向上能同时传递),因此每个方向必须单独地进行关闭.

(2)       当一方完成它的数据发送任务后就能发送一个F I N来终止这个方向连接。当一端收到一个F I N,它必须通知应用层另一端几经终止了那个方向的数据传送。发送F I N通常是应用层进行关闭的结果。

(3)       收到一个F I N只意味着在这一方向上没有数据流动。一个T C P连接在收到一个F I N后仍能发送数据。而这对利用半关闭的应用来说是可能的,尽管在实际应用中只有很少的T C P应用程序这样做。

(4)       首先进行关闭的一方(即发送第一个F I N)将执行主动关闭,而另一方(收到这个F I N)执行被动关闭。通常一方完成主动关闭而另一方完成被动关闭。

 

五、建立连接超时重连

有很多情况导致无法建立连接。一种情况是服务器主机没有处于正常状态。在这个输出中有趣的一点是客户间隔多长时间发送一个S Y N,试图建立连接。第2个S Y N与第1个的间隔是5 . 8秒,而第3个与第2个的间隔是2 4秒。

 

六、MSS和MTU

最大报文段长度( M S S)表示T C P传往另一端的最大块数据的长度。当一个连接建立时,连接的双方都要通告各自的M S S。

它并不是任何条件下都可协商。当建立一个连接时,每一方都有用于通告它期望接收的M S S选项(M S S选项只能出现在S Y N报文段中)。如果一方不接收来自另一方的M S S值,则M S S就定为默认值5 3 6字节(这个默认值允许2 0字节的I P首部和2 0字节的T C P首部以适合5 7 6字节I P数据报)。

报文段越大允许每个报文段传送的数据就越多,相对I P和T C P首部有更高的网络利用率。当T C P发送一个S Y N时,或者是因为一个本地应用进程想发起一个连接,或者是因为另一端的主机收到了一个连接请求,它能将M S S值设置为外出接口上的M T U长度减去固定的I P首部和T C P首部长度。

M S S让主机限制另一端发送数据报的长度。加上主机也能控制它发送数据报的长度,这将使以较小M T U连接到一个网络上的主机避免分段。

 

七、状态变迁图

7.1 客户端和服务端基本流程说明

粗线代表客户端流程,虚线代表服务端流程。细实线代表应用程序的一些操作。

两个导致进入E S TA B L I S H -E D状态的变迁对应打开一个连接,而两个导致从E S TA B L I S H E D状态离开的变迁对应关闭一个连接。E S TA B L I S H E D状态是连接双方能够进行双向数据传递的状态。

7.2 状态位说明

 

7.2.1 TIME_WAIT状态位

定义:T I M E _ WA I T状态也称为2 M S L等待状态。每个具体T C P实现必须选择一个报文段最大生存时间M S L(Maximum Segment Lifetime)。它是任何报文段被丢弃前在网络内的最长时间。

作用:

(1)当T C P执行一个主动关闭,并发回最后一个A C K,该连接必须在T I M E _ WA I T状态停留的时间为2倍的M S L。这样可让T C P再次发送最后的A C K以防这个A C K丢失(另一端超时并重发最后的F I N)。

(2)这种2 M S L等待的另一个结果是这个T C P连接在2 M S L等待期间,定义这个连接的插口(客户的I P地址和端口号,服务器的I P地址和端口号)不能再被使用。这个连接只能在2 M S L结束后才能再被使用。

某些实现和A P I提供了一种避开这个限制的方法。使用插口A P I时,可说明其中的S O _ R E U S E A D D R选项。它将让调用者对处于2 M S L等待的本地端口进行赋值,但我们

将看到TCP原则上仍将避免使用仍处于2MSL连接中的端口

在连接处于2 M S L等待时,任何迟到的报文段将被丢弃。因为处于2 M S L等待的、由该插口对(socket pair)定义的连接在这段时间内不能被再用.

客户端和服务端差异:

我们说图1 8 - 1 3中客户执行主动关闭并进入T I M E _ WA I T是正常的。服务器通常执行被动关闭,不会进入T I M E _ WA I T状态。这暗示如果我们终止一个客户程序,并立即重新启动这个客户程序,则这个新客户程序将不能重用相同的本地端口。这不会带来什么问题,因为客户使用本地端口,而并不关心这个端口号是什么。

然而,对于服务器,情况就有所不同,因为服务器使用熟知端口。如果我们终止一个已经建立连接的服务器程序,并试图立即重新启动这个服务器程序,服务器程序将不能把它的

这个熟知端口赋值给它的端点,因为那个端口是处于2 M S L连接的一部分。在重新启动服务器程序前,它需要在1 ~ 4分钟。

 

7.2.2 FIN_WAIT_2状态

在F I N _ WA I T _ 2状态我们已经发出了F I N,并且另一端也已对它进行确认。除非我们在实行半关闭,否则将等待另一端的应用层意识到它已收到一个文件结束符说明,并向我们发一个F I N 来关闭另一方向的连接。只有当另一端的进程完成这个关闭,我们这端才会从

F I N _ WA I T _ 2状态进入T I M E _ WA I T状态。

这意味着我们这端可能永远保持这个状态。另一端也将处于C L O S E _ WA I T状态,并一直保持这个状态直到应用层决定进行关闭。

许多伯克利实现采用如下方式来防止这种在F I N _ WA I T _ 2状态的无限等待。如果执行主动关闭的应用层将进行全关闭,而不是半关闭来说明它还想接收数据,就设置一个定时器。如果这个连接空闲1 0分钟7 5秒,T C P将进入C L O S E D状态。

 

7.3 复位报文段说明

一般说来,无论何时一个报文段发往基准的连接( referenced connection)出现错误, T C P都会发出一个复位报文段(这里提到的“基准的连接”是指由目的I P地址和目的端口号以及源I P地址和源端口号指明的连接。

(1)到不可达端口的连接请求

产生复位的一种常见情况是当连接请求到达时,目的端口没有进程正在听。对于U D P,我们在6 . 5节看到这种情况,当一个数据报到达目的端口时,该端口没在使用,它将产生一个I C M P端口不可达的信息。而T C P则使用复位。

C ---à S (NO PORT)

S ---à C (RST)

(2) 有序释放和无序释放

终止一个连接的正常方式是一方发送F I N。有时这也称为有序释放(orderly release),因为在所有排队数据都已发送之后才发送F I N,正常情况下没有任何数据丢失。但也有可能发送一个复位报文段而不是F I N来中途释放一个连接。有时称这为异常释放(abortive release)。

异常终止一个连接对应用程序来说有两个优点:

Ø         丢弃任何待发数据并立即发送复位报文段;

Ø         R S T的接收方会区分另一端执行的是异常关闭还是正常关闭。

应用程序使用的A P I必须提供产生异常关闭而不是正常关闭的手段。

Socket API通过“ linger on close”选项(S O _ L I N G E R)提供了这种异常关闭的能力。我们加上- L选项并将停留时间设为0。这将导致连接关闭时进行复位而不是正常的F I N。

 

7.4 半关闭/半打开/同时打开/关闭说明

半关闭

T C P提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。这就是所谓下载的半关闭。

描述如下:我已经完成了数据传送,因此发送一个文件结束( F I N)给另一端,但我还想接收另一端发来的数据,直到它给我发来文件结束(F I N)。

实现方式:如果应用程序不调用c l o s e而调用s h u t d o w n,且第2个参数值为1,则插口的A P I支持半关闭。

流程如下:

(1)初始端发出的F I N,接着是另一端对这个F I N的A C K报文段。

(2)但后面就和图1 8 - 4不同,因为接收半关闭的一方仍能发送数据。我们只显示一个数据报文段和一个A C K报文段,但可能发送了许多数据报文段(将在第1 9章讨论数据报

文段和确认报文段的交换)。

(3)当收到半关闭的一端在完成它的数据传送后,将发送一个F I N关闭这个方向的连接,这将传送一个文件结束符给发起这个半关闭的应用进程。

(4)当对第二个F I N进行确认后,这个连接便彻底关闭了。

 

半打开

如果一方已经关闭或异常终止连接而另一方却还不知道,我们将这样的T C P连接称为半打开(H a l f - O p e n)的。任何一端的主机异常都可能导致发生这种情况。只要不打算在半打开连接上传输数据,仍处于连接状态的一方就不会检测另一方已经出现异常。

半打开连接的另一个常见原因是当客户主机突然掉电而不是正常的结束客户应用程序后

再关机.

 

同时打开

两个应用程序同时彼此执行主动打开的情况是可能的,尽管发生的可能性极小。每一方

必须发送一个S Y N,且这些S Y N必须传递给对方。这需要每一方使用一个对方熟知的端口作为本地端口。这又称为同时打开( simultaneous open)。

例如,主机A中的一个应用程序使用本地端口7 7 7 7,并与主机B的端口8 8 8 8执行主动打开。主机B中的应用程序则使用本地端口8 8 8 8,并与主机A的端口7 7 7 7执行主动打开。

一个同时打开的连接需要交换4个报文段,比正常的三次握手多一个。此外,要注意的是

我们没有将任何一端称为客户或服务器,因为每一端既是客户又是服务器。

 

同时关闭

我们在以前讨论过一方(通常但不总是客户方)发送第一个F I N执行主动关闭。双方都执

行主动关闭也是可能的, T C P协议也允许这样的同时关闭( simultaneous close)。

在图1 8 - 1 2中,当应用层发出关闭命令时,两端均从E S TA B L I S H E D变为F I N _ WA I T _ 1。

这将导致双方各发送一个F I N,两个F I N经过网络传送后分别到达另一端。收到F I N后,状态由F I N _ WA I T _ 1变迁到C L O S I N G,并发送最后的A C K。当收到最后的A C K时,状态变化为T I M E _ WA I T。图1 8 - 1 9总结了这些状态的变化。

 

8、本地和远端地址和端口限制规范

我们知道U D P服务器通常在指定I P本地地址和本地端口外,还能指定远端I P地址和远端端口。RFC 793中显示的接口函数允许一个服务器在执行被动打开时,可指明远端插口(等待一个特定的客户执行主动打开),也可不指明远端插口(等待任何客户)。

遗憾的是,大多数A P I都不支持这么做。服务器必须不指明远端插口,而等待连接请求的到来,然后检查客户端的I P地址和端口号。

 

9、输入连接请求队列(backlog)

可能出现当服务器在创建一个新的进程时,或操作系统正忙于处理优先级更高的进程时,到达多个连接请求。当服务器正处于忙时(应用层忙), T C P是如何处理这些呼入的连接请求?(底层如何处理连接)

(1)正等待连接请求的一端有一个固定长度的连接队列,该队列中的连接已被T C P接受

(即三次握手已经完成),但还没有被应用层所接受。

注意区分T C P接受一个连接是将其放入这个队列,而应用层接受连接是将其从该队列中移出。

(2)       应用层将指明该队列的最大长度,这个值通常称为积压值( b a c k l o g )。它的取值范围是0 ~ 5之间的整数,包括0和5。积压值说明的是T C P监听的端点已被T C P接受而等待应用层接受的最大连接数。这个积压值对系统所允许的最大连接数,或者并发服务器所能并发处理的客户数,并无影响。

(3)       当一个连接请求(即S Y N)到达时,T C P使用一个算法,根据当前连接队列中的连接数确定是否接收这个连接。

(4)      如果对于新的连接请求,该T C P监听的端点的连接队列中还有空间(基于图1 8 - 2 3),T C P模块将对S Y N进行确认并完成连接的建立。但应用层只有在三次握手中的第三个报文段收到后才会知道这个新连接时。另外,当客户进程的主动打开成功但服务器的应用层还不知道这个新的连接时,它可能会认为服务器进程已经准备好接收数据了(如果发生这种情况,服务器的T C P仅将接收的数据放入缓冲队列)。也就是说应用层无法干预TCP连接的三次握手细节。

(5)       如果对于新的连接请求,连接队列中已没有空间, T C P将不理会收到的S Y N。也不发回任何报文段(即不发回R S T)。如果应用层不能及时接受已被T C P接受的连接,这些连接可能占满整个连接队列,客户的主动打开最终将超时。

 

 

应用层无法干预TCP底层三次握手细节:

 

这个例子中有一个巧妙之处,这在大多T C P / I P的具体实现中都能见到,就是如果服务器

的连接队列未满时, T C P将接受传入的连接请求(即S Y N),但并不让应用层了解该连接源于何处(即不告知源I P地址和源端口)。这不是T C P所要求的,而只是共同的实现技术(如伯克利源代码通常都这么做)。如果一个A P I如T L I(见1 . 1 5节)向应用程序提供了解连接请求的到来的方法,并允许应用程序选择是否接受连接。当应用程序假定被告知连接请求已经到来时,T C P的三次握手已经结束!其他运输层的实现可能将连接请求的到达与接受分开(如O S I的运输层),但T C P不是这样。

Solaris 2.2 提供了一个选项使T C P只有在应用程序说可以接受( t c p _ e a g e r _

l i s t e n e r s见E . 4),才允许接受传入的连接请求。

这种行为也意味着T C P服务器无法使客户进程的主动打开失效。当一个新的客户连接传

递给服务器的应用程序时, T C P的三次握手就结束了,客户的主动打开已经完全成功。如果服务器的应用程序此时看到客户的I P地址和端口号,并决定是否为该客户进行服务,服务器所能做的就是关闭连接(发送F I N),或者复位连接(发送R S T)。无论哪种情况,客户进程都认为一切正常,因为它的主动打开已经完成,并且已经向服务器程序发送过请求。

原创粉丝点击