13.1 引言
1、TCP的可靠传输,为了解决多种TCP状态时需要面对的大量问题
2、UDP的连接不需要进行建立与终止
3、TCP所面临的问题:一个连接何时建立、终止,在无警告的情况下重新启动
4、在连接的建立过程中,通信双方需要交换一些选项。这些选项被认为是连接的参数。这些选项只允许在连接建立时发送,而其他一些选项则能够稍后发送。
13.2 TCP 连接的建立与终止
一个TCP连接由四元组成:客户端IP地址、端口号,服务器IP地址、端口号。换句话说一个TCP连接由一对端点或套接字构成,其中通信每一端由一对(IP地址、端口号)所标识。
一个TCP连接分为三个阶段:启动、数据传输(建立与连接)、退出(关闭),为了建立一个TCP连接,需要完成以下步骤。
主动开启者(客户端)发送一个SYN报文段(同步序列编号,用于对接收方传递的SYN进行判断是否传输正确),并指明了它需要连接的端口号和它客户端的初始序列号(记为ISN)。客户端发送的这个SYN报文段称为段1.
服务器接收到该报文段后,会返回一个SYN报文段作为响应(在原有的基础下SYN报文序列号+1),同时返回一个ACK数值。TCP在传送的过程中,每传送一次都会在原有的SYN序列含基础下+1。此方法的目的用于判断TCP的传输是否发送错误,并重新传输。
为了确认服务器的SYN,客户端会再次发送一个SYN报文段以表示确认
过程传输图
序言:一个普通TCP连接的建立与终止。由客户端发起三次握手,该过程连接双方彼此交换SYN初始序列号。在通信双方必须发送了FIN数据包表明了连接终止信号。只有当连接双方都完成关闭操作后,才能算完整关闭;
TCP的关闭过程:
1.主动关闭者(通常为客户端)发送一个FIN报文段(其中包含了+1的ACK)
2.被动关闭者(通常为服务器)接受到后会返回一个ACK报文段(+1),表明接受并第二次发送一个FIN报文段以表示关闭的信号。此时上层应用会被告知连接另一端已经提出关闭请求。导致应用程序发起自己的关闭操作。接着被动关闭者转变为主动关闭者,发送自己FIN报文段
3.为了完成连接的关闭,最后发送的报文段还包含了一个ACK用于确认上一个FIN。为了确保主动关闭者已经接受到被动关闭者的FIN。(该过程中)此方法为了确保果出现FIN丢失的情况, 那么发送方将重新传输直到接收到一个ACK.确认为止。
13.2.1 TCP的半关闭
TCP的半关闭(客户端发起)指客户端发起了关闭请求,但希望服务器能继续发送数据,直到发送完后再进行关闭的情况,两个半关闭情况构成了一次完整的关闭。当接收方完成数据发送后,会发送一个FIN报文段来关闭本方的连接,服务器方还在继续传输数据,直到数据传输完成后,服务器才会发起一个FIN报文段指示关闭。只有2个FIN被确认后,整个连接才会关闭。
13.2.2 TCP的同时打开与关闭
1.该情况表明双方都是客户端与服务器,A主机的B端口发起请求,B主机的A端口发起响应。B主机的A端口发起请求,A主机的B端口发起响应。
13.2.3 初始序列号
在一个连接中,TCP报文段在经过网络路由后会发送各种情况(延迟抵达、排序混乱)的情况。为了解决问题,需要针对不同情况进行调整,序列号则会代表了这一过程。每一个连接都会有不同的序列号。FCO793]指出初始序列号可被视为一个32位的计数器。该计数器的数值每4 微秒加1
问题:1.如果连接由于某个报文段因网络延迟而被关闭,然后又以4元组重新打开,那么可以相信延迟的报文段会被重新进入视为有效数据而重新进入新连接的数据流中。此时需要采取一些措施步骤避免实例间的序列号的重叠问题。
13.2.4 连接建立超时
1.服务器关闭导致,发送一个不存在的主机导致。会收到ARP响应(无法找到IP地址)
解决办法:可在ARP表中建立一条记录,那么系统就不需要发送A R P 请求, 而会马上根据T C P / I P 协议尝试与这个不存在的主机建立联系
2.若导致上述会导致TCP请求方频繁建立连接并发送ACK报文段,会发生指数回退(后续描述)。每一次回退都是前一次次数的两倍。
3.一些系统可配置发送初始SYN报文的次数,例如选择相对较小的数值5。两次重新传输之间的指数回退是TCP拥塞管理响应的一部分。(此处涉及Karn算法)
13.2.6 连接与转换器
NAT方法:利用NAT进行IPv4与IPv6地址转换。
13.3 TCP选项
TCP头部包含了多个选项。
每个选项中代表了该TCP连接中包含了某种操作?
13.3.1 最大段大小选项
该选项表明TCP协议所允许从对方接收到的最大报文段,最大段报文段只记录TCP数据的字节数而不包括其他相关的TCP与IP头部。每条连接中都在SYN选项中表明自己允许的最大段大小。通常默认值为536字节。
13.3.1 选择确认选项
1.该选项解决问题:TCP不能正确确认之前已经接受的数据。由于接受的数据是无序的(路由网络的不确定性),所以接受的ACK是不确定的。TCP接收方的数据队列中会出现空洞。TCP接收方需要防止应用程序出现空洞数据
2.解决办法:TCP的选择确认解决了该问题,能在报文段丢失或接收方遗漏进行重传操作。
SACK选项块:其中包含了SACK信息,包含了接收方已经成功接受数据块的序列号范围。一个范围的操作称为SACK块。
13.3.1 窗口缩放选项
个人理解:每个窗口代表了一个数据内容,通过调整窗口缩放控制了传输的速率
13.3.2 时间戳选项与放回绕序列号
时间戳选项:通过该选项确认ACK往返时间,并通过时间灵活调整来确保传输速率,引出重传超时概念。通过时间戳来判断是否超时,中途发送了什么,从而重新将包发出。借助时间戳能够精确记出往返时间样本。(与重传计时器相关联)。
13.3.3 用户超时选项
1.该选项指明了TCP发送者在确认对方未能成功接受数据之前等待该数据ACK确认时间
13.3.4 认真选项
1.发送数据时,TCP根据共享密匙生成一个通信密匙,确保传输数据的安全性。
13.4 TCP路径最大传输单元发现
1.它是指经过两台主机之间路径的所以网络报文段中最大传输单元的最小值(即在路径中发现能够发现传输最大数据的路径)。因此它很大程度上控制了最后生成的IP数据包
2.根据通信双方声明的最大段大小来选择发送方的最大段大小。路径最大传输单元发现不允许发送超过对方所声音的最大段大小行为。如果对面未指明,则发送最小数值536字节(536+20+20)
3.采用二分搜索法;执行路径最大传输单元发现的协议必须能够快速检测消息丢弃并调整数据包大小
4.路由的动态变化会在减少段大小的数值一段时间后会尝试一个更大的数值。间隔约10分钟。
注意点:一条连接的两个方向的路径最大传输单元是不同的。
13.5 TCP状态转换
1.该状态表明了在一个连接的不同阶段发送的各种类型报文段。这些觉得TCP应该做什么的规则由TCP所属的状态决定的。当前状态会在各种触发条件发生变化。
2.有些转换会要求发送一些控制位字段置位的报文段。还有一些转换是由应用程序的动作或超时器引发的。
13.5.2 TIME_WAIT状态
1.该状态也称位2MSL等待状态,每个实现都必须为最大段生存期选择一个数值。代表任何报文段在被丢弃前允许存在的最长时间。IP数据报拥有TTL字段和跳数限制字段。这两个字段限制了IP数据报的有效生存时间。
2.若设定好了2MSL数值,代表了两倍最大生存时间,该情况为了TCP重新发送最终的ACK避免包丢失
重新发送最终的ACK并不是因为TCP重传了ACK.( 它们并不消耗序列号, 也不会被T C P 重传) , 而是因为通信另一方重传了它的FIN(它消耗一个序列号) 事实上,TCP总是重传FIN,直到它收到一个最终的ACK。
3.另一个影响2MSL等待状态的因素是当TCP处于等待状态时,双方将该定义为不可重新使用,只有等待该时间结束时。或通过允许时间戳选项来避免混淆,这条连接才能被再次使用
4.TCP规则会防止该端口处于2MSL等待状态的同一连接的其他实例重新使用。当处于该状态时,任何延迟到达的报文段将会被丢弃。当这条正确的连接被建立起来后,这条连接之前的实例所传输延迟报文段是不能被当作新连接的一部分来解读的。
5.通常客户端主动发起关闭操作进入该状态,服务器反之。
6.值得注意,由于一个客户端能够快速产生大量连接(同一服务器),因此它也可在临时端口号供应紧张时延迟一会来等待其他连接的终止。
7.对于服务器而言,如果我们终于一个已经建立了一条服务器的连接,并立即尝试重启它,服务器不能为该程序端分配对应端口号,因为终止连接时有2MSL等待状态,端口号仍是连接的一部分。根据系统对MSL设定值不同,服务器可能需要花费不同时间重启。
8.程序可设立优先级高于默认值的方式,这样即使处于2MSL等待状态的连接的一部分,仍然允许程序对其绑定。
9.2MSL状态能够防止新的连接状态将前一个延迟报文段解释成自身数据段的状况。该方法只有在处于2MSL等待状态的连接相关的主机未关闭的条件才具有意义。
13.5.2 静默时间的概念
如果一台处于TIME_WAIT状态的连接主机崩溃,任何在MSL内重新启动,并且使用崩溃前相同的IP、端口使用,那么该连接会被认为属于主机重启后创建的新连接。这种处理方式将不会考虑重启之后如何选择初始序列号的。
为防止上述情况发生,引出了静默时间的概念。指出在崩溃或重启后等待一个MSL时间
值得注意的是大多数程序崩溃或重启会大于一个MSL时间
13.5.3 FIN_WAIT状态
1.在该状态下,某TCP端(通常为客户端)发送一个FIN并已得到另一端确认确认。除非该TCP端出现半关闭,否则该TCP会一直等待另一端识别出自己已接受一个文件关闭的通知并关闭这一端引起发送FIN的连接(即等待另一端发送他的FIN关闭连接)。该TCP连接才会从FIN_WAIT状态转换为TIME_WAIT状态。
2.这意味着未收到另一端的FIN报文段,会一直处于该状态,对方也依然一直处于CLOSE_WAIT状态,并且能够永远维持这一状态并宣布它的关闭。
3.解决办法:若该连接不处于半关闭状态指明它还希望继续接受到数据,则会设立一个计时器。若计时器超时未接受到数据,该TCP连接就会转移到CLOSED状态。
13.5.4 同时打开与关闭的转换
1.当TCP经过专门的设计后能够处理同时打开,通信双方会同时发送SYN报文段,进入SYN_SEND状态,并同时接受对方发来的SYN报文段时会将状态迁移至SYN_RCVD,然后重新发送一个新的SYN确认之前接受到的SYN。当通信双方都接受到了SYN与ACK。状态会迁移至ESTABLISHED(数据传输状态)。
2.同时关闭时,通信双方都会从ESTABLISHED状态迁移至FIN_WAIT。此时会向对方发送一个FIN,本地通信端会从FIN_WAIT_1迁移至CLOSING。最后通信双方会发送ACK来确认将状态更改为TIME_WAIT状态。从而初始化2MSL过程。
13.6 重置报文段
1.当发现一个到达的报文段数据是不正确时,TCP会发送一个重置报文段(指重置报文段的4元组所指定的连接)。重置报文段通常会导致TCP连接的快速拆卸(发送端的快速拆卸)。
13.6.1 针对不存在端口的连接请求
1.通常情况一个连接请求到达本地IP地址但没有相关进程会产生一个重置报文段。
2.UDP中若出现到达IP地址但没有相应进程会产生一个ICMP目的地不可达消息
3.重置报文段中的ACK号等于初始序列号加上数据长度0,在加上SYN位的1字节。
13.6.2 终止一条连接
1.正常情况是通信一方发送一个FIN,来请求关闭称为有序释放,该FIN会等待数据全部发送出去后才会发出,而在任何时刻能够发送一个重置报文段取代FIN终止连接。
2.该方法导致任何排队的数据(后序排队传输的数据)都将被抛弃,重置报文段会立即发出;重置报文段的接收方会说明该方式为终止操作而不是正常关闭。接收方必须实现上述终止行为来取代正常关闭操作。
13.6.3 半开连接
1.在未告知另一端的情况下通信一段关闭或终止连接,那么该TCP状态则为半开状态(崩溃或电源切断)。
2.例子:例如客户端发生了非正常操作(电脑崩溃或切断电源操作),如果切断电源是没有发生数据传输。那么服务器永远不会知道客户端已经关闭连接,将会一直处于保持连接状态(ESTABLISHED)。等客户端再次开机时启动电脑并开启一个新会话时(相同的服务器),会导致服务器有很多半开的TCP连接(利用TCP的keepalive选项发现另一端已经消失)。
13.6.4 时间等待错误
1.当TCP一端处于TIME_WAIT状态时,该TCP一端接收到了延迟发送的一些报文段,或是特殊的重置报文段,它将会被破坏,被称为时间等待错误
2.解决办法:当处于TIME_WAIT状态时,它会认为序列号与ACK号数值都是旧的,当收到旧报文段时,TCP会发送一个ACK作为响应,其中包含了最新的序列号与ACK号。当服务器接收到该报文段后,没有这条连接的任何信息,因此会发送一个重置报文段作为响应,它会时客户端过早的从TIME_WAIT状态转移至CLOSED状态。
13.7 TCP服务器选项
1.指明服务器处理多个并发请求时,服务器是如何分配其他的资源。来了解TCP服务器如何使用端口号的,以及如何处理多个并发请求
13.7.1 TCP端口号
1.TCP协议不能仅仅根据目的端口号来决定与哪一个进程得到接收的报文段。只有处于LISTEN状态并接受进入的连接请求。处于ESTABLISHED状态的节点不能接受SYN报文段,处于LISTEN状态不能接受数据段。
13.7.2 限制本地IP地址
1.创建一个服务器地址,用于只能限定本地IP连接。若从目的地址不是本地地址连接服务器。该请求不会被TCP模块接受。因为拒接接受的操作是由操作系统的TCP模块根据该应用程序指定的本地IP地址与SYN报文段包含的目的地址所做出的。
13.7.3 限制外部节点
1.服务器不必指定客户端的节点,而是根据接收到的连接来检查IP地址与端口号
13.7.4 进入连接队列
1.发生问题:当操作系统忙于其他优先级高的进程或服务器在被伪造的连接请求攻击时,多个连接请求可能会到达。
2.当一个连接请求到达(SYN报文段),会检测系统范围的参数。如果处于SYN_RCVD状态的连接数量超过阈值,进入的连接会被拒绝。
3.当处于侦听状态时,该连接会被服务器所接受,但未被应用程序所接受。应用程序会对这一队列做出限制。
4.若侦听节点仍有空间分配新连接,TCP模块会应答SYN并完成连接。当三次握手完成后,收到3个报文段之后,与侦听节点相关的进程才会知道新的连接。当客户端进行相关操作,客户端无法知道服务器准备好没,然而服务器的应用程序可能还未收到新连接通知。TCP模块会把来的数据存入队列
5.若侦听节点没有足够空间分配新连接,TCP会对SYN做出延迟响应,Linux能够根据做出响应(即缓慢接受数据的时间)
6.队列溢出,发送重置报文并不可取。若发送重置报文,会误认为服务器不存在,而实际是繁忙的。解决办法:若队列已满(服务器的进程)放缓接受时间:使他既不会超时也不会时间(控制好接受的时间段)
13.9 总结
1.在两个进程使用TCP协议交换数据时,它们必须在彼此间建立一条数据的通道。
2.包括TCP建立连接的三次握手以及四次挥手(不包括半关闭和同时开启和关闭情况)
3.TCP选项(选择性确认、时间戳、最大段大小、TCP认证以及用户超时选项)
4.展示了连接的建立过程是如何超时的,重置报文段是如何发送与解析的,TCP的半关闭和同时打开和关闭
5.TCP约束了一个主动打开操作中尝试连接的次数,也约束了被动打开操作后能服务尝试连接次数。
6.TIME_WAIT的工作:维持两倍的最大段生存时间。若有新连接使用相同的4元组时,使用时间戳能够减少等待时间,同时能够有助于探测回绕序列号以及更好的测量往返时间。