注意这里会先走一个 tcp_checksum_complete(),目的是看看数据包的校验和(Checksum)是否合法 。
校验和可以验证数据从端到端的传输中是否出现异常 。由发送端计算,然后由接收端验证 。计算范围覆盖数据包里的TCP首部和TCP数据 。如果在发送端到接收端传输过程中,数据发生任何改动,比如被第三方篡改,那么接收方能检测到校验和有差错,此时TCP段会被直接丢弃 。如果校验和没问题,那才会发RST 。
所以,只有在数据包没问题的情况下,比如校验和没问题,才会发RST包给对端 。
为什么数据包异常的情况下,不发RST?一个数据包连校验都不能通过,那这个包,多半有问题 。

文章插图
有可能是在发送的过程中被篡改了,又或者,可能只是一个胡乱伪造的数据包 。
五层网络,不管是哪一层,只要遇到了这种数据,推荐的做法都是默默扔掉,而不是去回复一个消息告诉对方数据有问题 。
如果对方用的是TCP,是可靠传输协议,发现很久没有ACK响应,自己就会重传 。
如果对方用的是UDP,说明发送端已经接受了“不可靠会丢包”的事实,那丢了就丢了 。
因此,数据包异常的情况下,默默扔掉,不发RST,非常合理 。

文章插图
还是不能理解?那我再举个例子 。
正常人喷你,他说话条理清晰,主谓宾分明 。此时你喷回去,那你是个充满热情,正直,富有判断力的好人 。
而此时一个憨憨也想喷你,但他思维混乱,连话都说不清楚,一直阿巴阿巴的,你虽然听不懂,但大受震撼,此时你会?
- A:跟他激情互喷
- B:不跟他一般见识,就当没听过
这下,应该就懂了 。
程序启动了但是崩了端口不可用的场景里,除了端口未监听以外,还有可能是从前监听了,但服务端机器上做监听操作的应用程序突然崩了,此时客户端还像往常一样正常发送消息,服务器内核协议栈收到消息后,则会回一个RST 。在开发过程中,这种情况是最常见的 。
比如你的服务端应用程序里,弄了个空指针,或者数组越界啥的,程序立马就崩了 。

文章插图
TCP监听了但崩了
这种情况跟端口未监听本质上类似,在服务端的应用程序崩溃后,原来监听的端口资源就被释放了,从效果上来看,类似于处于CLOSED状态 。
此时服务端又收到了客户端发来的消息,内核协议栈会根据IP端口,从全局哈希表里查找sock,结果当然是拿不到对应的sock数据,于是走了跟上面"端口未监听"时一样的逻辑,回了个RST 。客户端在收到RST后也释放了sock资源,从效果上来看,就是连接断了 。
RST和502的关系上面这张图,服务端程序崩溃后,如果客户端再有数据发送,会出现RST 。但如果在客户端和服务端中间再加一个Nginx,就像下图一样 。

文章插图
RST与502
nginx会作为客户端和服务端之间的"中间人角色",负责转发请求和响应结果 。但当服务端程序崩溃,比如出现野指针或者OOM的问题,那转发到服务器的请求,必然得不到响应,后端服务端还会返回一个RST给nginx 。nginx在收到这个RST后会断开与服务端的连接,同时返回客户端一个502错误码 。
所以,出现502问题,一般情况下都是因为后端程序崩了,基于这一点假设,去看看监控是不是发生了OOM或者日志是否有空指针等报错信息 。
socket提前关闭这种情况分为本端提前关闭,和远端提前关闭 。
本端提前关闭如果本端socket接收缓冲区还有数据未读,此时提前close() socket 。那么本端会先把接收缓冲区的数据清空,然后给远端发一个RST 。

文章插图
recvbuf非空
远端提前关闭远端已经close()了socket,此时本端还尝试发数据给远端 。那么远端就会回一个RST 。

文章插图
close()触发TCP四次挥手
推荐阅读
- 图解TCP的通信机制
- 芍药与牡丹的区别图解,芍药和牡丹的区别
- 17年迈腾保养灯归零方法图解?老迈腾保养灯归零方法
- 百合种球埋深浅图解,个百合种球可以种多少
- 中国联通|136号段收到乱码短信!中国移动回应:联通分公司系统测试闹
- 阻尼铰链原理图解 万向铰链补偿器原理图
- tcl电视外接音箱图解 tcl 6200deg怎么接电脑音箱
- 菊花品种大全图解,菊花品种分类菊花品种介绍
- 星月菩提分类图解,佩戴星月菩提的意义
- 中草药6000种图解,图解教你正确的玉器挂件礼品绑法
