三十天学不会TCP,UDP/IP网络编程 - RST的用法
不知不觉也写了这么多了,继续我的自己的推广大业~完整版可以去gitbook(https://www.gitbook.com/@rogerzhu/)看到。
如果对和程序员有关的计算机网络知识,和对计算机网络方面的编程有兴趣,虽然说现在这种“看不见”的东西真正能在实用中遇到的机会不多,但是我始终觉得无论计算机的语言,热点方向怎么变化,作为一个程序员,很多基本的知识都应该有所了解。而当时在网上搜索资料的时候,这方面的资料真的是少的可怜,所以,我有幸前两年接触了这方面的知识,我觉得我应该把我知道的记录下来,虽然写的不一定很好,但是希望能给需要帮助的人多个参考。我的计划是用半年时间来写完这一系列文章,这个标题也是我对太多速成文章的一种态度,好了,废话不再多扯了,下面是其中的一节内容,更多内容可以去gitbook上找到。
在TCP的六个标识符里,有一个代表RST,reset,但是翻译成重置连接似乎也不太妥当,报告错误也不太合适,作为一个优雅而又逻辑合理的协议,RST对于TCP中出现的错误而导致两端都进入错误处理有重要的作用。
情况没有按照预想的进行
有句诗叫做“不如意事常八九,能与人言无二三”,作为一个庞大,复杂,系统的协议,TCP通信中经常都会出现不是一帆风顺的情况。比如前面提过,在三次握手的第二阶段,如果在几次重发都失败的情况下,会回复一个RST包。正是TCP有这个设计才能让TCP称得上连失败了都处理的很优雅。
为什么要有这么一个RST包而不是在结束的时候直接粗暴的结束或者说啥也不发生的结束呢?还是先让我们看看现实中打电话的例子,现实中总有那种妈妈给自己的儿子女儿打电话,儿子女儿不耐烦的,甚至产生冲突。而这个时候如果儿女这一端简单的把电话放下,妈妈那一端就只能听到环境声,对于这边的情况完全不了解。先不说这种对于对端极不礼貌的做法,至少这样让对端感到很担心,不知道那一边是怎么情况。而即使你再生气但是你说,不说了,不说了,我挂了,然后挂上电话,哪怕是很重的摔下电话。至少对端可以从嘟嘟声中知道对端已经挂了电话,不用担心前面描述的那种担心了。
TCP也是一样,如果没有这个RST包,那么出现出现异常的对端只能等待,因为他根本可能知道对端怎么了。在资源极端重要的网络环境里,这样的做法不仅浪费资源更重要的是让TCP这种号称核弹都炸不毁的协议陷入了一种混沌的状态,就像C/C++中的野指针一样,无法管理无序而又混乱。RST包几乎涵盖在TCP每个状态中,下面在介绍什么时候会发送RST包之前,先得了解一下正常的状态下的TCP各种状态变迁,这有了解了正常才能更好理解异常嘛。
TCP状态变迁图
我一直认为在计算机领域,有两个状态机图最经典,一个是进程调度时候的进程状态变迁图,第二个就是TCP状态变迁图了。这个图清晰的表示了在使用TCP协议通信时,从建立连接到释放连接的每个过程,如果你能不靠任何外力的情况下画出这张图,那么不得不说你已经对TCP的每个阶段了如执掌了,如果再理解下TCP中的流量控制等等,那么其实关于这方面的面试你完全不用担心了。
废话不多说了,我从网上挑了一张我觉得我看着最舒服的版本:
这上面的所有状态在前面两节都说过了,除了Established状态,这个状态表示TCP处于连接传输数据的状态,算是一个比较稳定的状态。相比于建立连接和终止连接,这个状态在状态本身上并没有什么特别的,就像一条路修完之后,车子就上去跑就行了。但是在连接状态下,TCP的太多设计哲学就蕴含在这里面了,我们现实中的道路管理要能借鉴里面的一些思想,很多拥堵情况都能避免了。
言归正传,在这个图中,状态很多,为了演示下怎么样去看这种状态机状态图,我就叙述下怎么样从这个图中找到三次握手中的种种状态变迁。
状态机图主要有两个部分组成,框框表示某种状态,框框之间用线条连接,标识状态的变迁,而在这些线条之上往往会写着一些说明,这些说明被誉为激励条件,一个状态只有经过了某种条件的刺激或者激励才能变迁为另一个状态。打个比方吧,比如你在发呆,你处于空闲状态,这个时候我打你一下,给你一个刺激,你就会从空闲状态变迁为疼痛状态了。
所有的状态都从Closed开始,在这个图的叙述中,有两条说明,实现表示客户,虚线表示服务器,准确的来说,这种说法并不严谨,因为在TCP的通信过程中其实没有服务器和客户之分,两边都在同等的发送数据。而在这个图或者一般的表述中,主动发起连接的那一方一般会被称之为客户端,被动接受的那一段是服务器端。在了解了这些先决条件之后,那么就来一起找找这个图中的三次握手在哪里吧。
首先看Closed状态中的实线,也就是表示客户的状态,在右边,主动发送SYN之后,进入SYN_SENT状态,三次握手第一步完成。而在这之后,收到SYN和ACK包,然后发送ACK之后客户这边就进入了连接状态。
然后再看看另一条路,从Closed状态虚线进入listen状态,这里不需要任何激励条件就能完成,因为默认服务器一直在监听客户发来的请求,不然那你这个图就画不下去了。在收到SYN,发送SYN和ACK之后进入SYN_RCVD状态,也就是三次握手的第二步。然后就是继续收到对端的ACK之后,进入连接状态。
每个状态机图都能很方便的变成很多独立的小单元,这也是一个状态机图绘画的好与不好的一个标志。好的状态机图状态之间变迁关系清晰,彼此耦合性很小。而差的你就感觉在这种状态变化的指示下只会变成一团混乱。
仔细看一下这个状态机图,你会发现很多前面并没有提及的有趣的状态,他们中很多都是很边缘的情况,但是作为一个严谨的协议设计者,应该最大可能留下最小的漏洞。比如图中你会发现从listen状态可以直接变成SYN_SEND状态,回想一下前面说了服务器端会默认为是listen状态从而可以监听对端来的请求。但是如果这个时候服务器端主动发送了SYN,那么他其实就是我们定义中的“客户”了,所以图中用实线标识这种情况下会SYN_SEND状态。
另外一个在发起连接阶段的时候的特殊情况就是SYN_SEND和SYN_RCVD中间那条线,如果一个客户在进入SYN_SEND同时收到对端发送回来的SYN请求,通俗点说就是两端同时发起了连接,两边都是客户了,这个时候TCP不会就此终止,而是进入SYN_RCVD,然后再经历后面的过程之后,两边都进入了Established状态。
这就是这张图的上半部分,如果有兴趣可以看看下半部分整个的关闭流程作为联系。
RST状态变迁图
在了解了正常状态变迁之后,异常状态就不会显得特别的乱了,在网上我找到了这么一张图,我觉得画的特别好,就拿来借用了。
对比上面的图,这张图用红色的部分标识了发送RST的情况,但是也简化了一些上面有的状态变迁,不过这对于了解整个TCP过程中RST的状态变迁没有那么重要了。
从这个图中第一个可以学到的知识就是经历所有RST状态之后,连接都会进入Closed状态,也就是结束。RST的状态基本分成两种,超时和包丢失。
首先看看超时的情况,在图中就三种包重传超时,SYN,FIN和数据包,可以看到超时都是某种“主动的动作”。比如在三次握手的第二个阶段,重传SYN+ACK一直超时,服务器端就只能发送一个RST到对端了。同理在FIN超时和本身传输数据超时之后,RST也会发送到对方。
第二类是丢失,其实本质上上和上一种情况是一直的,在ACK丢失的情况下,在对端看来就是发送包超时,所以在这种情况下主要是接收RST。
那么在现实生活中,什么样的情况会导致超时呢?其实很多情况都可能发生,比如某一端程序突然崩溃,某一端突然没电了等等,这种情况下都会引起超时,从而会导致RST包的发送。如果用官方的语言总结下,RST包会在以下三种情况下被发送:
到达的端口不存在,比如说在客户端发送SYNC想建立连接的时候,对端并没有任何监听端口,那么就会发生超时,从而发送RST包。而在UDP这种没有连接的协议中,一个ICMP端口不可达消息就能解决这个问题(如果你对这些名词很陌生,可以看看前面的文章了)。
连接被异常终止, 比如说应用程序崩溃了。
检测半关闭连接,这个半关闭的概念其实在上一篇的时候有所提及,但是不详细,这里正好说明一下。半关闭连接主要发生在某一段已经关闭或者异常终止但是另外一段并不知道的情况下。比如在通信的过程中,突然拔掉服务器那边的网线,然后再重启服务器和其应用程序。这个时候连接就处于一个半关闭状态,此时客户机再向对方发一个消息,服务器端会回复一个RST消息,本端就知道刚才发生了什么。
说了这么多,言而总之其实RST主要作用有两个,报告本端异常,告知对方错误,记住这两句话就差不多记住了RST包的作用。
三十天学不会TCP,UDP/IP网络编程 - RST的用法的更多相关文章
- 三十天学不会TCP,UDP/IP网络编程-IP头格式祥述
我又来了,这篇文章还是来做(da)推(guang)介(gao)我自己的!俗话说事不过三,我觉得我下次得换个说法了,不然估计要被厌恶了,但是我是好心呐,一定要相信我纯洁的眼神.由于这两年接触到了比较多的 ...
- 三十天学不会TCP,UDP/IP网络编程-ARP -- 连接MAC和IP
继续来做(da)推(guang)介(gao)我自己的!由于这两年接触到了比较多的这方面的知识,不想忘了,我决定把他们记录下来,所以决定在GitBook用半年时间上面写下来,这是目前写的一节,目前已完成 ...
- 三十天学不会TCP,UDP/IP网络编程-TraceRoute的哲学
新年快乐,继续来部分粘贴复制我的这一系列文章啦,如果对和程序员有关的计算机网络知识,和对计算机网络方面的编程有兴趣,欢迎去gitbook(https://www.gitbook.com/@rogerz ...
- 三十天学不会TCP,UDP/IP网络编程 - 绅士的开始
经过了过年的忙碌和年初的懈怠一切的日子,我又开始重新更新了~这是最新的一篇~完整版可以去gitbook(https://www.gitbook.com/@rogerzhu/)看到. 如果对和程序员有关 ...
- 三十天学不会TCP,UDP/IP网络编程-UDP,从简单的开始
如果对和程序员有关的计算机网络知识,和对计算机网络方面的编程有兴趣,欢迎去gitbook(https://www.gitbook.com/@rogerzhu/)star我的这一系列文章,虽然说现在这种 ...
- 三十天学不会TCP,UDP/IP网络编程 - UDP的实践--DHCP
在经历了一顿忙碌加出去玩了玩之后,我又开始重新更新了~这是最新的一篇~完整版可以去gitbook(https://www.gitbook.com/@rogerzhu/)看到,在gitbook的后台流量 ...
- 三十天学不会TCP,UDP/IP网络编程 -- TCP中的智慧之连续ARQ
突然发现上一篇文章贴图有问题,关键我怎么调也调不好,为了表达歉意,我再贴一篇gitbook上的吧,虽然违背了我自己的隔一篇在这里发一次的潜规则~其余完整版可以去gitbook(https://www. ...
- 三十天学不会TCP,UDP/IP网络编程 -- RTT的计算
欢迎去gitbook(https://www.gitbook.com/@rogerzhu/)看到完整版. 如果对和程序员有关的计算机网络知识,和对计算机网络方面的编程有兴趣,虽然说现在这种“看不见”的 ...
- 三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层
这篇文章主要是来做(da)推(guang)介(gao)的!由于这两年接触到了比较多的这方面的知识,不想忘了,我决定把他们记录下来,所以决定在GitBook用半年时间上面写下来,这是目前写的一节,后面会 ...
随机推荐
- TensorFlow4Delphi
https://github.com/hartmutdavid/TensorFlow4Delphi
- textarea只允许上下调节尺寸
对于extarea,因为如果不做限制的话,它是可以自由调节尺寸的,对于这一点我相信用户是非常喜欢的,因为每个人都有自己认为合适的尺寸,但是对于前端来说就比较头疼了,因为随意调节宽高,就会破坏整体布局, ...
- Golang http 服务器
package main import ( "net/http" "fmt" ) func main() { app := http.NewServeMux() ...
- numpy模块中的sum(axis)方法
1.sum函数声明 sum(a, axis=None, dtype=None, out=None, keepdims=<class 'numpy._globals._NoValue'>) ...
- HDU - 1584 IDA*
思路:裸的IDA*,估计当前状态至少需要多少距离才能达到目标状态,剪枝即可.每一墩牌只需记录其最上面和最下面的牌型即可完成移动. AC代码 #include <cstdio> #inclu ...
- 在SpringBoot中存放session到Redis
前言 今天你们将再一次领略到SpringBoot的开发到底有多快,以及SpringBoot的思想(默认配置) 我们将使用redis存放用户的session,用户session存放策略有很多,有存放到内 ...
- mysql 导出每张表中的100条数据..............
windows下配好MYSQL 环境变量,cmd 然后: mysqldump -uroot -p123 [数据库名]--where "1=1 limit 100" --lock-a ...
- java I/O框架 (三)基本流
概述 基本流有字节输入输出流(InputStream,OutputStream),和字符输入输出流(Reader,Writer),它们都是抽象类,作为Java IO API中其他所有流的父类存在. 我 ...
- 常用u-boot命令详解(全)
U-boot发展到现在,他的命令行模式已经非常接近Linux下的shell了,命令行模式模式下支持"Tab"键的命令补全和命令的历史记录功能.而且如果你输入的命令的前几个字符和别的 ...
- R语言数据集合并、数据增减、不等长合并
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 数据选取与简单操作: which 返回一个向量 ...