RST报文详解_modbus网关使用方法

RST报文详解_modbus网关使用方法我们知道TCP建立连接的时候需要三次连接,TCP释放连接的时候需要四次挥手,在这个过程中,出现了很多特殊的标志报文段,例如SYNACKFIN,在TCP协议中,除了上面说了那些标志报文段之外,还有其他的报文段,如PUSH标志报文段以及今天需要重点讲解的RST报文段。RST:(Resettheconnection)用于复位因某种原因引起出现的错误连接,也用来拒绝非法数据和请求。如果接收到R…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

我们知道TCP建立连接的时候需要三次连接,TCP释放连接的时候需要四次挥手,在这个过程中,出现了很多特殊的标志报文段,例如SYN ACK FIN,在TCP协议中,除了上面说了那些标志报文段之外,还有其他的报文段,如PUSH标志报文段以及今天需要重点讲解的RST报文段。

RST:(Reset the connection)用于复位因某种原因引起出现的错误连接,也用来拒绝非法数据和请求。如果接收到RST位时候,通常发生了某些错误;

发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓冲区中的包,发送RST;接收端收到RST包后,也不必发送ACK包来确认。

“Connection reset”的原因是服务器关闭了Connection[调用了Socket.close()方法]。大家可能有疑问了:服务器关闭了Connection为什么会返回“RST”而不是返回“FIN”标志。原因在于Socket.close()方法的语义和TCP的“FIN”标志语义不一样:发送TCP的“FIN”标志表示我不再发送数据了,而Socket.close()表示我不在发送也不接受数据了。问题就出在“我不接受数据” 上,如果此时客户端还往服务器发送数据,服务器内核接收到数据,但是发现此时Socket已经close了,则会返回“RST”标志给客户端。当然,此时客户端就会提示:“Connection reset”。

产生RST报文的几种情景

  • 目的地为某端口的SYN到达,然而该端口上没有正在监听的服务器;

客户端发起三次握手,发送完第一个SYN分节之后,收到来自服务器的RST分节(个人理解,分节就是报文段?)。

RST分节的内容:如果收到的是ACK报文,RST取ACK报文的ACK序列号为RST报文的SEQ;如果报文不是ACK报文,RST的SEQ为0且ACK字段为收到的报文SEQ+报文长度;

  • 请求超时

一个客户端连接服务器,connect返回-1并且error=EINPROGRESS。 直接telnet发现网络连接没有问题。ping没有出现丢包。用抓包工具查看,客户端是在收到服务器发出的SYN之后就莫名其妙的发送了RST。

这是为什么呢? 
原因就是请求超时了。

有89、27两台主机。主机89向主机27发送了一个SYN,表示希望连接8888端口,主机27回应了主机89一个SYN表示可以连接。但是主机27却很不友好,莫名其妙的发送了一个RST表示我不想连接你了。

后来经过排查发现,在主机27上的程序在建立了socket之后,用setsockopt的SO_RCVTIMEO选项设置了recv的超时时间为100ms。而我们看上面的抓包结果表示,从主机89发出SYN到接收SYN的时间多达110ms。(从15:01:27.799961到15:01:27.961886, 小数点之后的单位是微秒)。因此主机27上的程序认为接收超时,所以发送了RST拒绝进一步接收数据。

  • 想取消一个已存在的连接

操作系统接收到的来自TCP连接中的每一个字节,我都会让应用程序接收到。如果应用程序不接收怎么办?发送RST。

打开一个socket然后连接一个服务器并发送5000个字节。刚才我们看服务器的代码,每次只接收4096个字节,那么就是说客户端发送的剩下的4个字节服务端的应用程序没有接收到,服务器端的socket就被关闭掉,这种情况下会发生什么状况呢,还是抓包看一看。

前三行就是TCP的3次握手,从第四行开始看,客户端的49660端口向服务器的9877端口发送了5000个字节的数据,然后服务器端发送了一个ACK进行了确认,紧接着服务器向客户端发送了一个RST断开了连接。

如果想提前关闭一个连接,就需要发送RST报文段。

  • 客户端在服务端已经关闭掉socket之后,仍然在发送数据。

假设server和client 已经建立了连接,server调用了close(Socket.close()方法的语义和TCP的“FIN”标志语义不一样:发送TCP的“FIN”标志表示我不再发送数据了,而Socket.close()表示我不在发送也不接受数据了。) 发送FIN 段给client,此时server不能再通过socket发送和接收数据,此时client调用read,如果接收到FIN 段会返回0,但client此时还是可以write 给server的,write调用只负责把数据交给TCP发送缓冲区就可以成功返回了,所以不会出错,而server收到数据后应答一个RST段,表示服务器已经不能接收数据,连接重置,client收到RST段后无法立刻通知应用层,只把这个状态保存在TCP协议层。**如果client再次调用write发数据给server,由于TCP协议层已经处于RST状态了,因此不会将数据发出,而是发一个SIGPIPE信号给应用层,SIGPIPE信号的缺省处理动作是终止程序。 
当一个进程向某个已收到RST的套接字执行写操作时,(此时写操作返回EPIPE错误)内核向该进程发送一个SIGPIPE信号,该信号的默认行为是终止进程,因此进程必须捕获它以免不情愿地被终止;**

  • TCP接收到一个根本不存在的连接上的分节;

TCP接收到一个根本不存在的连接上的分节;服务器主机崩溃后重启:它的TCP丢失了崩溃前的所有连接信息,因此服务器TCP对于所有收到的来自客户的数据分节响应一个RST;

总结出现RST报文的场景:

1.connect一个不存在的端口;
2.向一个已经关掉的连接send数据;
3.向一个已经崩溃的对端发送数据(连接之前已经被建立);
4.close(sockfd)时,直接丢弃接收缓冲区未读取的数据,并给对方发一个RST。这个是由SO_LINGER选项来控制的;
 5.a重启,收到b的保活探针,a发rst,通知b。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/187150.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 个人网站开发流程(网站开发的工作流程图)

    1.确定主题选择主题应该是小而精,目标定位要小,内容要精。不要去试图制作一个包罗万象的站点,这往往会失去网站的特色,也会带来高强度的劳动,给网站的及时更新带来困难。一定记住,在互联网只有第一,没有第二。2.选择域名在互联网世界中,域名就是网站的名字。一个好记,易记得域名会给个人网站加分,当积累了一定的用户的人气的个人网站,域名的价值就会体现出来。3.学习网页设计和开发技术对于常…

    2022年4月14日
    44
  • plsqldev设置中文_plsql13安装以及配置

    plsqldev设置中文_plsql13安装以及配置1、查看服务端编码selectuserenv(‘language’)fromdual;然后将查询到的服务器编码,配置到环境变量,保证客户端与服务器端编码一致。2、配置环境变量计算机–>右键属性–>高级系统设置–>环境变量–>系统变量,新建…

    2022年10月28日
    0
  • 学习微机原理与接口这一篇就够了

    学习微机原理与接口这一篇就够了注意问题:由于这篇文章我是用WORD编辑的,写完以后,发现没办法转换为MD格式,所以我只能用截图的形式上传了,写这篇文章的主要目的是对微机原理与接口基础知识的一个简单梳理。…

    2022年10月2日
    0
  • leetcode 最长有效括号_字符指针赋值为什么不能加大括号

    leetcode 最长有效括号_字符指针赋值为什么不能加大括号给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。示例 1:输入:s = “(()”输出:2解释:最长有效括号子串是 “()”示例 2:输入:s = “)()())”输出:4解释:最长有效括号子串是 “()()”示例 3:输入:s = “”输出:0题解括号匹配:(看作+1,)看作-1,所有满足条件的括号应该是前缀和>=0,并且总和==0class Solution {public: const int INF =

    2022年8月9日
    1
  • JAVA常见类(十二)Calendar类

    JAVA常见类(十二)Calendar类Calendar类Calendar:它为特定瞬间与一组诸如YEAR、MONTH、DAY_OF_MONTH、HOUR等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。一、构造方法protectedCalendar():由于修饰符是protected,所以无法直接创建该对象。需要通过别的途径生成该对象。二、成员方法Calendar类…

    2022年9月24日
    0
  • thinkphp3.2如何自动生成后台模块并且怎么访问

    thinkphp3.2如何自动生成后台模块并且怎么访问

    2021年10月21日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号