zoukankan      html  css  js  c++  java
  • TCP ------ RST的产生

     产生RST的几个原因

    1、请求超时

    有89、27两台主机。主机89向主机27发送了一个SYN,表示希望连接8888端口,主机27回应了主机89一个SYN表示可以连接。但是主机89莫名其妙的发送了一个RST表示我不想连接你了。经过排查发现,在主机89上的程序在建立了socket之后,用setsockopt的SO_RCVTIMEO选项设置了recv 的超时时间为100ms。而抓包结果表示,从主机89发出SYN到接收SYN的时间多达110ms。因此主机89上的程序认为接收超时,所以发送了RST拒绝进一步发送数据。

    2、只要TCP栈的读缓冲里还有未读取(read)数据,则调用close时会直接向对端发送RST。比如客户端一次发送100个字节,但是服务器read设置最多读取90个,read一次后就不再read,所以还有10个在缓冲区,服务器执行close,服务器会发送RST

    如果客户端第一次发送100个字节,服务器read最多读取100个,read一次把数据全部读出来了,然后客户端再发送100个字节,但是服务器没有read,执行close,执行的是四次挥手

    推断:有两个接收缓冲区,一个是应用层层面,一个是传输层层面,使用read会把数据从传输层层面搬运到应用层层面,只有应用层层面有数据然后close才会发送RST

    3、端口未打开

    主机241向主机114发送一个SYN请求,表示想要连接主机114的40000端口,但是主机114上根本没有打开40000这个端口,于是就向主机241发送了一个RST

    4、server端调用close()或者调用shutdown()关闭读之后,client端write

    当server端close套接字的时候,假设此时server端的接收缓冲区没有数据了。则close发送的是FIN,client端如果收到FIN之后,调用read函数,是返回0的,因为FIN的接收,表明client端以后再无数据可以接收,因为对方发来FIN,就表明对方不再发送数据了。然后client发送应答ack报文,表明收到FIN报文,server收到ack报文之后,就进去了FIN_WAIT_2阶段,根据tcp协议,向一个 FIN_WAIT2 状态的服务 TCP(已 ACK 响应 FIN 分节)写入数据不成问题,所以此时我们可以在client端调用write函数,写入client端的发送缓冲区,由tcp连接,发送到server的接收缓冲区。但是此时,由于server端已经关闭了socket(Socket.close()方法的语义和TCP的“FIN”标志语义不一样:发送TCP的“FIN”标志表示我不再发送数据了,而Socket.close()表示我不再发送也不接受数据了),所以此时的接收缓冲区的内容都被抛弃,同时server端返回RST。收到RST的client端,如果调用read函数,读取,是返回ECONNRESET错误的

    client接收到RST后会出现两种情况:

    1、client端调用了read函数,知道server端发送了RST,但是我们的client对这个RST错误,不采取处理,继续调用write,write()会返回 epipe 错误,内核将向客户进程发送 SIGPIPE 信号,该信号默认会使进程终止(此时该前台进程未进行 core dump)。所以,向一个 FIN_WAIT2 状态的服务 TCP(已 ACK 响应 FIN 分节)写入数据不成问题,但是写一个已接收了 RST 的 Socket 则是一个错误。

    2、client收到RST段后无法立刻通知应用层(比如来不及调用read函数),只把这个状态保存在TCP协议层。如果client再次调用write发数据给server,write()会返回 epipe 错误,由于TCP协议层已经处于RST状态了,因此不会将数据发出,而是发一个SIGPIPE信号给应用层,SIGPIPE信号的缺省处理动作是终止程序。

    server端调用shutdown()关闭读通道,client端还继续向server端发送数据,此时server端会发送一个RST给client端

    5、keepalive数据包可达对方,但是对方端口号不存在

    6、使用SO_LINGER规定close()行为是发送RST,而不是发送FIN。

     

    7、服务器端和客户端建立好连接,服务器断网重启,端口号不变,此时客户端没有检测到服务器重启仍向服务器发送数据,则收到服务器发来的RST;同样的,客户端断网,重新连接网络,但是没有连接服务器,此时服务器没有检测到客户端断网重连仍向客户端发送数据,则收到客户端发来的RST

    8、进程奔溃(比如Qt编写的上位机由于内存释放导致进程异常退出),会发送RST

    9、客户端或服务器 FIN_WAIT_2 超时,发送RST 

    ------以上有很多条(比如3、4、5、7)符合一个规律(收到RST):数据发到对方,对方连着网络(即IP存在),但是端口不存在或者其他信息被清除了,则发送方会收到对方发来的RST

    ------其他情况属于主动发送RST

    RST介绍

    1. 发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓冲区中的包,发送RST。

    2. 而接收端收到RST包后,也不必发送ACK包来确认。接收端收到RST知道发送端是异常关闭

  • 相关阅读:
    mysql报错:java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone.
    MD5登陆密码的生成
    15. 3Sum、16. 3Sum Closest和18. 4Sum
    11. Container With Most Water
    8. String to Integer (atoi)
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    几种非线性激活函数介绍
    AI初探1
    AI初探
  • 原文地址:https://www.cnblogs.com/god-of-death/p/7236439.html
Copyright © 2011-2022 走看看