vlambda博客
学习文章列表

TCP协议的RST标志位

“TCP首部字段有6个是flags,每个标志位有特殊的含义,它们可以单独存在,也可以同时存在。对于接收方,不同的标志位代表不同的意思,需要做正确的处理”


01
Flags

可以在链接https://support.huawei.com/hedex/hdx.do?docid=EDOC1000105967查看各协议层协议首部字段及其含义


TCP协议首部格式



上图标注的红圈里有6个标志位,每个标志位占用一个比特


URG

紧急指针有效标识。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)


ACK

确认序号有效标识。只有当ACK=1时确认号字段才有效。当ACK=0时,确认号无效


PSH

标识接收方应该尽快将这个报文段交给应用层。接收到PSH = 1的TCP报文段,应尽快的交付接收应用进程,而不再等待整个缓存都填满了后再向上交付


RST

重建连接标识。当RST=1时,表明TCP连接中出现严重错误(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立连接


SYN

同步序号标识,用来发起一个连接。SYN=1表示这是一个连接请求或连接接受请求


FIN

发端完成发送任务标识。用来释放一个连接。FIN=1表明此报文段的发送端的数据已经发送完毕,并要求释放连接


02
RST


RST,Reset,复位标志,用于非正常地关闭连接。它是TCP协议首部里的一个标志位。发送RST包关闭连接时,直接丢弃缓冲区的包发送RST包(这个和发FIN包不同)。而接收端收到RST包后,也不必发送ACK包来确认


如何触发

正常地关闭连接用FIN标志位,但FIN标志位不能用来处理异常情况


  • 举例


客户端和服务器TCP连接正常,突然服务器掉电重启,与客户端的TCP连接状态由于掉电而完全消失。之后,客户端发给服务器任何消息,都会触发服务器发RST作为回应。服务器之所以发RST,是因为连接不存在,通过Reset状态位,间接告诉客户端异常情况的存在。如果Reset顺利到达客户端,客户端意识到异常发生了,会立马释放该TCP连接所占用的内存资源(状态、数据)、以及端口号,且不会回复ACK

  • 连接未监听的端口

连接一个未监听的端口,则被连接方会发送一个RST。也就是说主机传输层TCP程序接收到一个SYN包,而这个SYN包目的端口并没有socket监听,那么主机的协议栈会直接回复一个RST

  • 目的主机或网络路径中的防火墙拦截

如果目的主机或者网络路径中显式的设置了对数据包的拦截

使用iptables对主机的防火墙添加了一条规则,对于目的端口是60000的TCP报文,丢弃并回复RST

  • socket接收缓冲区Recv-Q中的数据未完全被应用程序读取时关闭该socket

接收到的数据缓存在缓冲区Recv-Q,它们等待被上层应用取走,如果缓冲区Recv-Q有数据未被应用取走,而此时调用了socket.close()方法强行关闭TCP连接,那么TCP协议程序发送的就不是FIN,而是RST

  • 向已关闭的socket发送数据

顾名思义,主机传输层TCP协议程序接收到一条TCP数据报,而目的端口并没有socket监听,那么主机的协议栈会直接回复一个RST

  • 向已关闭的连接发送FIN

主机传输层TCP协议程序接收到一条FIN,而目的端口并没有socket监听,那么主机的协议栈会直接回复一个RST


  • 向已经消逝的连接中发送数据
和上面的举例相同

  • 请求超时后收到回复

主机创建socket,设置SO_RCVTIMEOUT选项为100ms,向对端发送SYN,过了100ms后才收到ACK+SYN,那么主机的协议栈会直接回复一个RST

  • SO_LINGER

socket设置SO_LINGER选项,socket调用close()函数时,会直接丢弃缓冲区Send_Q未发完的数据,并发送RST

  • Linux下启用TIME_WAIT快速回收 

修改/etc/sysctl.conf中内核参数:

net.ipv4.tcp_tw_recycle = 1

当收到的SYN包的timestamp比上次的小时,就会发RST

TCP socket在任何状态下,只要收到RST包,即可进入CLOSED初始状态,不会有任何回应。至于是否通知上层应用,要根据应用程序是阻塞模式还是非阻塞模式:
阻塞模型下,内核无法主动通知应用层出错,只有应用层主动调用read()或者write()这样的IO系统调用时,内核才会利用出错来通知应用层对端RST

非阻塞模型下,select或者epoll会返回sockfd可读,应用层对其进行读取时,read()会报错RST

03
总结

  • FIN是客户端或服务器正常关闭tcp连接发的包,发送缓冲区Send-Q数据发完才会发FIN
  • RST是客户端或服务器异常关闭tcp连接发的包,通常都是主机收到不存在的tcp通道的tcp报文,主机“被迫”回复RST告知对方tcp连接异常,收到RST的一方就会关闭这个socket,释放所有socket信息,且不会回复ACK




扫描二维码关注“车载以太网测试”