服务端主动终止连接的情况分析

来源:互联网 发布:linux mmap使用场景 编辑:程序博客网 时间:2024/06/09 15:57

前面我们已经学习了基本的网络套接字编程,下面是与本文相关的网络编程源码github连接:
https://github.com/clearoff/Network-Code/tree/master/%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%92%8C%E5%AE%A2%E6%88%B7%E7%AB%AF(1V1)
然后下面我们给出与本文相关的博客连接,因为涉及到了TCP的“三次握手和四次挥手过程”:
http://blog.csdn.net/bit_clearoff/article/details/60478661

正常退出情况

首先我们来看看一次服务器和客户端正常通信的情况。
在这之前,让我们看看TCP的三次握手与四次挥手的过程。

首先是三次握手过程。
三次握手

下来是四次挥手过程。
这里写图片描述


下面我们结合着套接字编程,来看看TCP的这些过程(代码请点击上面的github连接).
这里写图片描述
当我们只打开服务端时,此时由于客户端没有向服务端发出连接请求,所以服务端此时处在LISTEN状态,这个状态称为监听状态,表示服务端在等待客户端的连接请求报文。

这里写图片描述
这次我们打开客户端,并且通过客户端向服务端发送数据,服务端页正常接收到了数据,此时服务端和客户端都处于ESTABLISHED状态,表示连接已经建立完成,即此时三次握手这个过程已经完毕,但是大家应该清楚,中间还有两次状态的切换客户端的SYN-SENT 以及 服务端的SYN-RCV.由于我们是手动监视,所以我们不能显示的看到这两个状态。

这里写图片描述
上图中,客户端在数据通信完成后想要结束掉与服务端的连接状态,我们直接通过按Ctrl + C 键向客户端发送了信号将客户端终止,此时,服务端应该也会向客户端发送ACK 字段的报文 相当于我们完成了四次挥手过程中的前两次挥手,通过指令的查看,我们发现结果确实也是那样,随后我们在Ctrl + C 掉服务端,完成了后两次挥手,整个通信过程也就完成了。


连接异常终止的情况

上面的正常过程中,我们是让客户端比服务端先退出,这样满足了四次挥手过程的要求;现在我们让服务器在客户端前面退出,我们来看看这个过程发生了什么。
由于我们研究的情况是连接的异常终止情况,所以三次握手状态我们就不关心了,这里我们这研究连接的异常终止情况。
这里写图片描述
上图中,我们让服务端先退出,然后我们用netstat观察端口的状态,此时我们发现四次挥手过程中服务器和客户端的状态颠倒了, 也就是说,服务端和客户端的进程那个先向对方发送FIN 字段报文,那么哪个就先进入FIN_WAIT2状态。

这里写图片描述

上图发生的原因是这样的,当服务器进程被终止时,会关闭其打开的所有文件描述符,此时就会向客户端发送一个FIN 的报文,客户端则响应一个ACK 报文,但是这样只完成了“四次挥手”的前两次挥手,也就是说这样只实现了半关闭,客户端仍然可以向服务器写入数据。
但是当客户端向服务器写入数据时,由于服务器端的套接字进程已经终止,此时连接的状态已经异常了,所以服务端进程不会向客户端发送ACK 报文,而是发送了一个RST 报文请求将处于异常状态的连接复位; 如果客户端此时还要向服务端发送数据,将诱发服务端TCP向服务端发送SIGPIPE信号,因为向接收到RST的套接口写数据都会收到此信号. 所以说,这就是为什么我们主动关闭服务端后,用客户端向服务端写数据,还必须是写两次后连接才会关闭的原因。

大家可以在自己的Linux系统实验一下,用tcpdump去抓包效果会更好。

1 0
原创粉丝点击