先介绍一个知识点:
当TCP最后一次握手结束后,也就是客户端发送ACK后,客户端不会立即释放资源。会先将状态转换为TIME-WAIT然后等到2-MSL(Maximum Segment Lifetime)后,才会释放资源。
1. 客户端发送结束(FIN)数据包给服务端,暗示客户端将要把建立的连接断开,这样的行为称为active close(FIN=1, seq=u)。
2. 服务端发送确认收到FIN的数据包(ACK=1, seq=v, ack=u+1)。
3. 服务端继续发送结束(FIN)数据包给客户端,这样的行为称为passive close(FIN=1, ACK=1, seq=w, ack=u+1)。
4. 客户端收到服务端的FIN数据包后发送确认报文(ACK=1, seq=u+1, ack=w+1)
下面是官方的例子
下面是个人的例子:
C++客户端
#include <QCoreApplication>
#include <QDebug>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QUrl>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QNetworkAccessManager manager;
QNetworkRequest request;
request.setUrl(QUrl("http://127.0.0.1:8080/test"));
QNetworkReply *reply = manager.get(request);
QObject::connect(reply, &QNetworkReply::finished, [&](){
qDebug() << reply->readAll();
qApp->exit();
});
return a.exec();
}
Java服务端,关键代码:
package cn.it1995.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping("/test")
public String test(){
return "test";
}
}
抓到的包如下:
客户端发送FIN数据包,其中Seq为155,
服务端接收到客户端的FIN数据包后,返回ACK应答。其中ack为155+1
然后服务端发送给客户端FIN数据包。
最后客户端回一个ACK应答。