本文主要是介绍TCP/IP协议详解卷一:Chapter18 笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
TCP/IP协议详解卷一:Chapter18 笔记
- Chapter 18 TCP连接的建立与终止
- 18.2 连接的建立与终止
- 18.3 连接建立的超时
- 18.4 最大报文段长度
- 18.5 TCP的半关闭
- 18.6 TCP的状态变迁图
- 18.7 复位报文段
- 18.8 同时打开
- 18.9 同时关闭
- 18.10 TCP选项
- 18.11 TCP服务器的设计
Chapter 18 TCP连接的建立与终止
18.2 连接的建立与终止
在系统svr4上键入如下命令:
svr4 % telnet bsdi discard
Trying 140.252.13.35 ...
Connected to bsdi.
Escape charcater is '^]'.
^]
telnet> quit
Connection closed.
telnet命令在与丢弃(discard)服务对应的端口上与主机bsdi建立一条TCP连接。这服务类型正是我们需要观察的一条连接建立与终止的服务类型,而不需要服务器发起任何数据交换。
建立连接协议
对应的时间系列如图:
报文段1、2、3完成连接的建立。这个过程也称为三次握手(three-way handshake)。报文4、5、6、7为正常关闭连接的过程。
- 请求端(称为客户)发送一个SYN段指明客户打算连接的服务器的端口,以及初始序号(ISN,在本例中为1415531521)。这个SYN段为报文段1。
- 服务器发回包含服务器的初始序号的SYN报文段(报文段2)作为应答。同时,将确认序号设置为客户的ISN加1以对客户的SYN报文段进行确认。一个SYN将占用一个序号。
- 客户必须将确认序号设置为服务器的ISN加1以对服务器的SYN报文段进行确认(报文段3)。
字段1415531521:1415531521(0)表示分组的序号是1415531521,而报文段中数据字节数为0。tcpdump显示这个字段的格式是开始的序号、一个冒号、隐含的结尾序号及圆括号内的数据字节数。这个字段只有在满足条件(1)报文段中至少包含一个数据字节;或者(2)SYN、FIN或RST被设置为1时才显示。
连接终止协议
建立一个连接需要3次握手,而终止一个连接要经过4次握手。这是由TCP的半关闭(half-close)造成的。既然一个TCP连接是全双工(即数据在两个方向上能同时传递),因此每个方向必须单独地进行关闭。这原则就是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向连接。发送FIN通常是应用层进行关闭的结果。首先进行关闭的一方(即发送第一个FIN)将执行主动关闭,而另一方(收到这个FIN)执行被动关闭。通常一方完成主动关闭而另一方完成被动关闭。
上图中报文段4发起终止连接,它由Telnet客户端关闭连接时发出。这在我们键入quit命令后发生。它将导致TCP客户端发送一个FIN,用来关闭从客户到服务器的数据传送。当服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。同时TCP服务器还向应用程序(即丢弃服务器)传送一个文件结束符。接着这个服务器程序就关闭它的连接,导致它的TCP端发送一个FIN(报文段6),客户必须发回一个确认,并将确认序号设置为收到序号加1(报文段7)。
18.3 连接建立的超时
有很多情况导致无法建立连接。一种情况是服务器主机没有处于正常状态。
18.4 最大报文段长度
最大报文段长度(MSS)表示TCP传往另一端的最大块数据的长度。当一个连接建立时,连接的双方都要通告各自的MSS。MSS让主机限制另一端发送数据报的长度。加上主机也能控制它发送数据报的长度,这将使以较小MTU连接到一个网络上的主机避免分段。
当建立一个连接时,每一方都有用于通告它期望接收的MSS选项(MSS选项只能出现在SYN报文段中)。如果一方不接收来自另一方的MSS值,则MSS就定为默认值536字节(这个默认值允许20字节的IP首部和20字节的TCP首部以适合576字节IP数据报)。
一般说来,如果没有分段发生, MSS还是越大越好。报文段越大允许每个报文段传送的数据就越多,相对IP和TCP首部有更高的网络利用率。当TCP发送一个SYN时,或者是因为一个本地应用进程想发起一个连接,或者是因为另一端的主机收到了一个连接请求,它能将MSS值设置为外出接口上的MTU长度减去固定的IP首部和TCP首部长度。对于一个以太网, MSS值可达1460字节。使用IEEE 802.3的封装,它的MSS可达1452字节。
如果目的IP地址为“非本地的(nonlocal)”,MSS通常的默认值为536。而区分地址是本地还是非本地是简单的,如果目的IP地址的网络号与子网号都和我们的相同,则是本地的;如果目的IP地址的网络号与我们的完全不同,则是非本地的;如果目的IP地址的网络号与我们的相同而子网号与我们的不同,则可能是本地的,也可能是非本地的。
18.5 TCP的半关闭
TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。这就是所谓的半关闭。
下图显示了一个半关闭的典型例子。
18.6 TCP的状态变迁图
下面的TCP状态变迁图展示了前文介绍的许多有关发起和终止TCP连接的规则。
其中:
收:说明当收到TCP报文段时的状态变迁;
发:说明为了进行某个状态变迁需要发送的TCP报文段。
粗的实线箭头表示正常的客户端状态变迁,用粗的虚线箭头表示正常的服务器状态变迁。
两个导致进入ESTABLISHED状态的变迁对应打开一个连接,而两个导致从ESTABLISHED状态离开的变迁对应关闭一个连接。ESTABLISHED状态是连接双方能够进行双向数据传递的状态。
2MSL等待状态
TIME_WAIT状态也称为2MSL等待状态。每个具体TCP实现必须选择一个报文段最大生存时间 MSL(Maximum Segment Lifetime)。它是任何报文段被丢弃前在网络内的最长时间。
对一个具体实现所给定的MSL值,处理的原则是:当TCP执行一个主动关闭,并发回最后一个ACK,该连接必须在TIME_WAIT状态停留的时间为2倍的MSL。这样可让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并重发最后的FIN)。这种2MSL等待的另一个结果是这个TCP连接在2MSL等待期间,定义这个连接的插口(客户的IP地址和端口号,服务器的IP地址和端口号)不能再被使用。
在连接处于2MSL等待时,任何迟到的报文段将被丢弃。因为处于2MSL等待的、由该插口对(socket pair)定义的连接在这段时间内不能被再用,因此当要建立一个有效的连接时,来自该连接的一个较早替身(incarnation)的迟到报文段作为新连接的一部分不可能不被曲解(一个连接由一个插口对来定义。一个连接的新的实例 instance 称为该连接的替身)。
平静时间
对于来自某个连接的较早替身的迟到报文段, 2MSL等待可防止将它解释成使用相同插口对的新连接的一部分。但这只有在处于2MSL等待连接中的主机处于正常工作状态时才有效。
如果使用处于2MSL等待端口的主机出现故障,它会在MSL秒内重新启动,并立即使用故障前仍处于2MSL的插口对来建立一个新的连接吗?RFC 793指出TCP在重启动后的MSL秒内不能建立任何连接。这就称为平静时间(quiet time)。
FIN_WAIT_2状态
在FIN_WAIT_2状态我们已经发出了FIN,并且另一端也已对它进行确认。除非我们在实行半关闭,否则将等待另一端的应用层意识到它已收到一个文件结束符说明,并向我们发一个FIN来关闭另一方向的连接。只有当另一端的进程完成这个关闭,我们这端才会从FIN_WAIT_2状态进入TIME_WAIT状态。
18.7 复位报文段
TCP首部中的RST比特是用于“复位”的。一般说来,无论何时一个报文段发往基准的连接(referenced connection)出现错误, TCP都会发出一个复位报文段(此处的“基准的连接”是指由目的IP地址和目的端口号以及源IP地址和源端口号指明的连接。RFC 793称之为插口)。
到不存在的端口的连接请求
产生复位的一种常见情况是当连接请求到达时,目的端口没有进程正在听。对于UDP,当一个数据报到达目的端口时,该端口没在使用,它将产生一个ICMP端口不可达的信息。而TCP则使用复位。
需要注意的值是复位报文段中的序号字段和确认序号字段。ACK比特在到达的报文段中没有被设置为1,复位报文段中的序号被置为0,确认序号被置为进入的ISN加上数据字节数。尽管在到达的报文段中没有真正的数据,但SYN比特从逻辑上占用了1字节的序号空间;因此,在这个例子中复位报文段中确认序号被置为ISN与数据长度(0)、SYN比特所占的1的总和。
异常终止一个连接
终止一个连接的正常方式是一方发送FIN。有时这也称为有序释放(orderly release),因为在所有排队数据都已发送之后才发送FIN,正常情况下没有任何数据丢失。但也有可能发送一个复位报文段而不是FIN来中途释放一个连接。有时称这为异常释放(abortive release)。
异常终止一个连接对应用程序来说有两个优点:(1)丢弃任何待发数据并立即发送复位报文段;(2)RST的接收方会区分另一端执行的是异常关闭还是正常关闭。Socket API通过“ linger on close”选项(SO_LINGER)提供了这种异常关闭的能力。需要注意的是RST报文段不会导致另一端产生任何响应,另一端根本不进行确认。收到RST的一方将终止该连接,并通知应用层连接复位。
检测半打开连接
如果一方已经关闭或异常终止连接而另一方却还不知道,我们将这样的TCP连接称为半打开(half-open)的。任何一端的主机异常都可能导致发生这种情况。
半打开连接的另一个常见原因是当客户主机突然掉电而不是正常的结束客户应用程序后再关机。由于服务器的TCP已经重新启动,它将丢失复位前连接的所有信息,因此它不知道数据报文段中提到的连接。TCP的处理原则是接收方以复位作为应答。
18.8 同时打开
两个应用程序同时彼此执行主动打开的情况是可能的,尽管发生的可能性极小。每一方必须发送一个SYN,且这些SYN必须传递给对方。这需要每一方使用一个对方熟知的端口作为本地端口。这又称为同时打开(simultaneous open)。例如,主机A中的一个应用程序使用本地端口7777,并与主机B的端口8888执行主动打开。主机B中的应用程序则使用本地端口8888,并与主机A的端口7777执行主动打开。
TCP是特意设计为了可以处理同时打开,对于同时打开它仅建立一条连接而不是两条连接。一个同时打开的连接需要交换4个报文段,比正常的三次握手多一个。此外,要注意的是,每一端既是客户又是服务器。
18.9 同时关闭
双方都执行主动关闭也是可能的, TCP协议也允许这样的同时关闭(simultaneous close)。同时关闭与正常关闭使用的段交换数目相同。
18.10 TCP选项
由第17章可知,TCP首部可以包含选项部分。仅在最初的TCP规范中定义的选项是选项表结束、无操作和最大报文段长度MSS。新的RFC定义了新的TCP选项,下图显示了当前TCP选项的格式,这些选项的定义出自于RFC 793和RFC 1323。
每个选项的开始是1字节kind字段,说明选项的类型。kind字段为0和1的选项仅占1个字节。其他的选项在kind字节后还有len字节。它说明的长度是指总长度,包括kind字节和len字节。设置无操作选项的原因在于允许发方填充字段为4字节的倍数。kind值为4、5、6和7的四个选项称为选择ACK及回显选项。回显选项已被时间戳选项取代,而目前定义的选择ACK选项仍未定论,并未包括在RFC 1323中。
18.11 TCP服务器的设计
大多数的TCP服务器进程是并发的。当一个新的连接请求到达服务器时,
服务器接受这个请求,并调用一个新进程来处理这个新的客户请求。不同的操作系统使用不同的技术来调用新的服务器进程。在Unix系统下,常用的技术是使用fork函数来创建新的进程。如果系统支持,也可使用轻型进程,即线程(thread)。
限定的本地IP地址
如果我们为sock程序指明一个IP地址(或主机名),并将它作为服务器,那么该IP地址就成为处于LISTEN服务器的本地I P地址。例如
sun % sock -s 140.252.1.29 8888
使这个服务器程序的连接仅局限于来自SLIP接口(140.252.1.29)。如果我们从主机solaris通过SLIP链路与这个服务器相连接,它将正常工作。但如果我们试图从以太网(140.252.13)中的主机与这个服务器进行连接,连接请求将被TCP模块拒绝。
限定的远端IP地址
下面的表格总结了TCP服务器进行连接时三种类型的地址绑定。在三种情况中, lport是服务器的熟知端口,而localIP必须是一个本地接口的IP地址。表中行的顺序正是TCP模块在收到一个连接请求时确定本地地址的顺序。最常使用的绑定(第1行,如果支持的话)将最先尝试,最不常用的(最后一行两端的IP地址都没有制定)将最后尝试。
呼入连接请求队列
当服务器在创建一个新的进程时,或操作系统正忙于处理优先级更高的进程时,到达多个连接请求。当服务器正处于忙时, TCP是如何处理这些呼入的连接请求?
在伯克利的TCP实现中采用以下规则:
- 正等待连接请求的一端有一个固定长度的连接队列,该队列中的连接已被TCP接受(即三次握手已经完成),但还没有被应用层所接受。
- 应用层将指明该队列的最大长度,这个值通常称为积压值(backlog)。
- 当一个连接请求(即SYN)到达时,TCP使用一个算法,根据当前连接队列中的连接数来确定是否接收这个连接。应用层的积压值与端点所能允许接受连接的最大数目有关(但并不相等)。
- 如果对于新的连接请求,该TCP监听的端点的连接队列中还有空间,TCP模块将对SYN进行确认并完成连接的建立。
- 如果对于新的连接请求,连接队列中已没有空间,TCP将不理会收到的SYN。也不发回任何报文段(即不发回RST)。
这篇关于TCP/IP协议详解卷一:Chapter18 笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!