theme: condensed-night-purple
断开连接
完成数据发送的一方发起断开连接的请求,http版本不同发起方也不同
- http1. 0情况下服务器发送完响应数据就会发起断开请求
- http1.1情况下服务器发送完数据后客户端还可以继续发送数据,因此发起断开连接的一方是客户端。
生成断开连接请求包
先假设是客户端发起的断开连接请求
客户端
客户端调用socket程序库的close程序,该程序会委托协议栈生成一个包含断开连接信息的tcp头部(fin比特为1),委托ip模块将数据发送给服务端,并更改当前socket状态(断开连接)
服务端
服务端的协议栈收到后也会改变服务端的socket状态并告知客户端收到断开连接的请求包(发送一个ack确认包);客户端调用read时协议栈会告知数据已经全部接受完成,客户端接下来就会调用close,生成fin比特为1的包,委托ip模块发送,服务器收到后确认发送ack包就结束了
删除套接字
断开连接操作后,套接字中的控制信息就会被清除,也就不需要这个套接字了,但是,套接字删除是要等待一段时间的,不能立马删除。
当碰到下面这个操作时就会造成问题:
假设服务器先发起的断开连接操作:
假设客户端发送的fin包丢失了,此时服务器的套接字信息已经删除了,并且正好服务器的另外一个程序要使用套接字(复用的正好是之前的那个套接字)。
客户端没有收到ack号就会重新发送fin包,这时候服务器的另外一个应用程序接受到的就是断开连接请求,就会导致混乱。
因此会等待一段时间才会删除套接字,这个时间是并不是固定的,协议栈并没有规定,一般是等待几分钟。
网络包的重传可能会持续几分钟,如果重发一定次数还是无效,就会断开连接
协议栈这块的转发讲完了,之后就开始分析下一层了委托IP模块的处理了。