TCP有限状态机转换

这里写图片描述
注:主动、被动与服务器、客户端没有明确的对应关系。
每个连接均开始于CLOSED状态。当一方执行了被动的连接原语(LISTEN)或主动的连接原语(CONNECT)时,它便会脱离CLOSED状态。如果此时另一方执行了相对应的连接原语,连接便建立了,并且状态变为ESTABLISHED。任何一方均可以首先请求释放连接,当连接被释放后,状态又回到了CLOSED。
这里写图片描述
CLOSED: 表示初始状态。
LISTEN: 表示服务器端的某个SOCKET处于监听状态,可以接受连接了。
SYN_RCVD: 这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用netstat很难看到这种状态的,除非特意写一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此该状态下收到客户端的ACK报文后,它会进入到ESTABLISHED状态。
SYN_SENT: 表示客户端已发送SYN报文,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。
ESTABLISHED:表示连接已经建立了。
FIN_WAIT_1: 其实FIN_WAIT_1和FIN_WAIT_2状态都表示等待对方的FIN报文。
**而这两种状态的区别是:**FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。
FIN_WAIT_2:实际上FIN_WAIT_2状态下的SOCKET,表示半连接,即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。
TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。在FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
CLOSING: 表示双方都正在关闭SOCKET连接,属于一种比较罕见的例外状态。正常情况下,当发送FIN报文后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING状态表示发送FIN报文后,并没有收到对方的ACK报文,反而却收到了对方的FIN报文。如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,即出现CLOSING状态。
CLOSE_WAIT: 表示在等待关闭。当对方close一个SOCKET后发送FIN报文给自己,你毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来真正需要考虑的事情是查看是否还有数据发要送给对方,如果没有的话,那么就可以close这个SOCKET,发送FIN报文给对方,即关闭连接。所以在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。
LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。
关闭的状态转换:假设通信双方是A,B;A主动发起关闭
(1)主动发起关闭方
A首先主动发起FIN报文,准备关闭TCP连接,然后进入FIN_WAIT1状态;
如果A收到了ACK报文,进入FIN_WAIT2状态,说明B还有数据发给A。不久之后,B发送FIN给A,然后,A发送ACK,并进入TIME_WAIT状态。
如果A收到到了ACK + FIN,A直接进入TIME_WAIT状态。
经过2个MSL,没有收到FIN信号,那么TIME_WAIT就自动转化为CLOESD。
(2)被动接收方
B在收到A的FIN报文后,知道A准备关闭 TCP连接了(注意只是A单方面关闭发数据的连接,也就是说A还可以接收数据)。B将发送ACK给A,进入CLOSED_WAIT状态。如果此时B也有数据发送给A,那么就一直发送好了,反正A不会发数据了。此时A处于FIN_WAIT2状态。当B的数据发送完毕之后,那么B发送FIN给 A,B进入LAST_ACK状态,当收到A发过来的ACK信号后,A进入CLOSED状态。
这里写图片描述
为什么TIME_WAIT状态要进过2个MSL(Maximum Segment Lifetime.)才能进入CLOSED状态?
由于网路存在不可靠的因素,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,重发可能丢失的ACK报文的过程最多需要2MSL,所以如果过了2MSL,没有再次收到B的FIN,那么说明之间A发出的ACK被B收到了,因此可以可靠关闭连接。
同时打开
两个应用程序同时执行主动打开的情况是可能的,虽然发生的可能性较低。
每一端都发送一个SYN,并传递给对方,且每一端都使用对端所知的端口作为本地端口。
例如:主机A中一应用程序使用77作为本地端口,并连接到主机B 99端口做主动打开。
主机B中一应用程序使用99作为本地端口,并连接到主机A 77端口做主动打开。
TCP协议在遇到这种情况时,只会打开一条连接。
这个连接的建立过程需要4次数据交换,而一个典型的连接建立只需要3次交换(即3次握手)
但多数伯克利版的TCP/IP实现并不支持同时打开。
这里写图片描述
SYN_RCVD与SYN_SEND都是转换为ESTABLISHED的中间状态,目标是两端均转换到ESTABLISHED状态。
同时关闭
如果应用程序同时发送FIN,则在发送后会首先进入FIN_WAIT_1状态。在收到对端的FIN后,回复一个ACK,会进入CLOSING状态。在收到对端的ACK后,进入TIME_WAIT状态。这种情况称为同时关闭。
同时关闭也需要有4次报文交换,与典型的关闭相同。
这里写图片描述
TCP三次握手建立连接&&四次握手关闭连接
1、建立连接协议(三次握手)
这里写图片描述
(1)建立连接时,客户端A发送SYN包(seq=J)到服务器B,并进入SYN_SENT状态,等待服务器B确认。

(2) 服务器B收到SYN包,必须确认客户A的SYN(ACK=J+1),同时自己也发送一个SYN包(seq=k),即SYN+ACK包,此时服务器B进入SYN_RCVD状态。

(3) 第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。

至此3次握手结束,TCP连接就建立起来了,然后客户端与服务器开始交互数据。上面描述过程中,SYN包表示TCP数据包的标志位syn=1,同理,ACK表示TCP报文中标志位ack=1,SYN+ACK表示标志位syn=1和ack=1同时成立。
2、终止连接协议(四次握手)
这里写图片描述
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接,
收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
 (1) TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
 (2) 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1,和SYN一样,一个FIN将占用一个序号。
 (3) 服务器关闭客户端的连接,发送一个FIN给客户端。
 (4) 客户段发回ACK报文确认,并将确认序号设置为收到序号加1。
为什么建立连接协议是三次握手,而关闭连接却是四次握手?
这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你未必会马上会关闭SOCKET,即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
为什么三次握手能可靠地建立连接?
在建立连接的时候,发起方发出请求(即发出SYN报文),接收方收到后必须给发起方一个回应(ACK+SYN)
(a)如果发起方没有收到接收方的ACK+SYN报文,说明报文丢失,必须重发请求;
如果发起方收到ACK+SYN报文
(b)不向接收方发出ACK信号(也就是只有两次握手,此时开始传递报文),那么从接收方的角度来看,它认为自己发出的ACK+SYN报文丢失了,发起方没有收到,所以它会再次重发。
(c) 向接收方发出ACK信号,没有收到接收方再次发来的ACK+SYN报文,那么说明接收方收到了自己发出的ACK报文,所以可以建立连接了。
举个例子保障可靠通信:
现在A和B两支军队准备在10:00同时发起进攻,如何才能保证这两支军队同时呢?
现在A发出电报,“要求在10:00同时发起进攻”;B收到后必须向A回复【收到,可以】
A在收到【收到,可以】的消息后,知道B已经收到了自己发出的消息。
站在B的角度去思考:我发出了【收到,可以】的消息,A必须要给我一个回应。如果我没有收到回应,那么就说明我的这个消息没有送到A那里去,那么就得再传一次【收到,可以】的消息给A。
所以A必须再次发出【OK】消息给B,此时,如果A没有再次收到B发来的【收到,可以】的消息,就可以认为自己的【OK】已经送给了B;
而如果B收到A发来的【OK】消息,说明自己此前发出的【收到,可以】已经被A收到。这样可以保证可靠通信。

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
目 录 译者序 前言 第1章 概述 1 1.1 引言 1 1.2 分层 1 1.3 TCP/IP的分层 4 1.4 互联网的地址 5 1.5 域名系统 6 1.6 封装 6 1.7 分用 8 1.8 客户-服务器模型 8 1.9 端口号 9 1.10 标准化过程 10 1.11 RFC 10 1.12 标准的简单服务 11 1.13 互联网 12 1.14 实现 12 1.15 应用编程接口 12 1.16 测试网络 13 1.17 小结 13 第2章 链路层 15 2.1 引言 15 2.2 以太网和IEEE 802封装 15 2.3 尾部封装 17 2.4 SLIP:串行线路IP 17 2.5 压缩的SLIP 18 2.6 PPP:点对点协议 18 2.7 环回接口 20 2.8 最大传输单元MTU 21 2.9 路径MTU 21 2.10 串行线路吞吐量计算 21 2.11 小结 22 第3章 IP:网际协议 24 3.1 引言 24 3.2 IP首部 24 3.3 IP路由选择 27 3.4 子网寻址 30 3.5 子网掩码 32 3.6 特殊情况的IP地址 33 3.7 一个子网的例子 33 3.8 ifconfig命令 35 3.9 netstat命令 36 3.10 IP的未来 36 3.11 小结 37 第4章 ARP:地址解析协议 38 4.1 引言 38 4.2 一个例子 38 4.3 ARP高速缓存 40 4.4 ARP的分组格式 40 4.5 ARP举例 41 4.5.1 一般的例子 41 4.5.2 对不存在主机的ARP请求 42 4.5.3 ARP高速缓存超时设置 43 4.6 ARP代理 43 4.7 免费ARP 45 4.8 arp命令 45 4.9 小结 46 第5章 RARP:逆地址解析协议 47 5.1 引言 47 5.2 RARP的分组格式 47 5.3 RARP举例 47 5.4 RARP服务器的设计 48 5.4.1 作为用户进程的RARP服务器 49 5.4.2 每个网络有多个RARP服务器 49 5.5 小结 49 第6章 ICMP:Internet控制报文协议 50 6.1 引言 50 6.2 ICMP报文的类型 50 6.3 ICMP地址掩码请求与应答 52 6.4 ICMP时间戳请求与应答 53 6.4.1 举例 54 6.4.2 另一种方法 55 6.5 ICMP端口不可达差错 56 6.6 ICMP报文的4.4BSD处理 59 6.7 小结 60 第7章 Ping程序 61 7.1 引言 61 7.2 Ping程序 61 7.2.1 LAN输出 62 7.2.2 WAN输出 63 7.2.3 线路SLIP链接 64 7.2.4 拨号SLIP链路 65 7.3 IP记录路由选项 65 7.3.1 通常的例子 66 7.3.2 异常的输出 68 7.4 IP时间戳选项 69 7.5 小结 70 第8章 Traceroute程序 71 8.1 引言 71 8.2 Traceroute 程序的操作 71 8.3 局域网输出 72 8.4 广域网输出 75 8.5 IP源站选路选项 76 8.5.1 宽松的源站选路的traceroute 程序示例 78 8.5.2 严格的源站选路的traceroute 程序示例 79 8.5.3 宽松的源站选路traceroute程序 的往返路由 80 8.6 小结 81 第9章 IP选路 83 9.1 引言 83 9.2 选路的原理 84 9.2.1 简单路由表 84 9.2.2 初始化路由表 86 9.2.3 较复杂的路由表 87 9.2.4 没有到达目的地的路由 87 9.3 ICMP主机与网络不可达差错 88 9.4 转发或不转发 89 9.5 ICMP重定向差错 89 9.5.1 一个例子 90 9.5.2 更多的细节 91 9.6 ICMP路由器发现报文 92 9.6.1 路由器操作 93 9.6.2 主机操作 93 9.6.3 实现 93 9.7 小结 94 第10章 动态选路协议 95 10.1 引言 95 10.2

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值