前言:TCP中有几个比较重要的标志位, SYN ACK FIN RST PSH URG。
比如:
(B) --> [SYN] -->(A)
(B)<-- [SYN/ACK] <--(A)
(B)--> [ACK] --> (A)
以上是三次握手建立连接的过程。以上字段的具体含义:
SYN: 表示建立连接
FIN: 表示关闭连接
ACK: 表示响应
PSH: 表示有 DATA数据传输
RST: 表示连接重置。
1、RST介绍
RST表示复位,引用TCP圣经里面的描述“一般说来,无论何时一个报文段发往基准的连接(referenced connection)出现错误,TCP都会发出一个复位报文段(这里提到的“基准的连接”是指由目的IP地址和目的端口号以及源IP地址和源端口号指明的连接)”。
2、什么情况下出现RST
(1)、到不存在的端口的连接请求(目标端口未打开)
产生复位的一种常见情况就是当连接请求到达时,目的端口没有进程正在监听(对于UDP这种情况下将会产生一个ICMP端口不可达的信息),这时TCP则使用复位。
(2)、异常终止一个连接(提前关闭一个连接)
正常情况下,有序释放一个连接是当所有排队数据都已经发送之后才发送FIN,这种情况下没有数据丢失。但也有可能发送一个复位报文段而不是FIN来中途释放一个连接——异常释放。
举个例子:
关于TCP,我想我们在教科书里都读到过一句话,'TCP是一种可靠的连接'。 而这可靠有这样一种含义,那就是操作系统接收到的来自TCP连接中的每一个字节,我都会让应用程序接收到。如果应用程序不接收怎么办?你猜对了,RST。
看两段程序:
这一段是server的最简单的代码。逻辑很简单,监听一个TCP端口然后当有客户端来连接的时候fork一个子进程来处理。注意看的是这一段fork里面的处理:
然后再看一下client的代码:
前三行就是TCP的3次握手,从第四行开始看,客户端的49660端口向服务器的9877端口发送了5000个字节的数据,然后服务器端发送了一个ACK进行了确认,紧接着服务器向客户端发送了一个RST断开了连接。和我们的预期一致。
可以推测,在一个已关闭的socket上收到数据,也就是说,如果某个socket已经关闭,但它这时依然收到数据也会产生RST。
(3)、检测半打开连接
如果一方已经关闭或异常终止连接而另一方却还不知道,我们将这样的TCP连接称为半打开(Half-Open)的。任何一端的主机异常都可能导致发生这种情况。只要不打算在半打开连接上传输数据,仍处于连接状态的一方就不会检测另一方已经出现异常。半打开连接的另一个常见原因是当客户主机突然掉电而不是正常的结束客户应用程序后再关机。这可能发生在使用PC机作为 Telnet的客户主机上,例如,用户在一天工作结束时关闭PC机的电源。当关闭PC机电源时,如果已不再有要向服务器发送的数据,服务器将永远不知道客户程序已经消失了。当用户在第二天到来时,打开PC机,并启动新的 Telnet客户程序,在服务器主机上会启动一个新的服务器程序。这样会导致服务器主机中产生许多半打开的TCP连接。
TCP在处理半打开连接时的处理原则是接收方以复位作为应答。