HTTP之Last-Modified、Etage、If-Modified-Since理论与实践(C++ Qt实现)
发布日期:2021-06-30 11:01:02 浏览次数:2 分类:技术文章

本文共 3966 字,大约阅读时间需要 13 分钟。

目录

 

 


 

基本理论

首先要理解缓存是如何被创建的:

浏览器首先先本地缓存发起创建请求,如果命中则返回数据给浏览器;

如果没有命中,就向代理服务器发起缓存,如果命中代理服务器会发给浏览器以及本地缓存;

如果没命中,则向资源服务器发起创建请求,然后资源服务器再给代理缓存,本地缓存,浏览器数据;

 

如果要实现这样的功能:

1. 浏览器本地有缓存,但每次还要向服务器发起请求,看看资源是不是更新了;

2. 如果更新了服务器发送新资源给浏览器,如果没更新就叫浏览器读取缓存;

 

要使用HTTP实现上面的功能,要具备以下的知识点:

1.  服务器响应头中的no-cahce为每次发起请求都要在服务器那边验证下,如果服务器能让浏览器使用本地缓存,才能使用。no-store为本地和代理服务器都不能存储缓存;每次都要拿新的。

2. 服务器响应头中有两根验证头,一个是Last-Modified和一个Etag。

3. Last-Modified为上次修改时间,配合请求头中的If-Modified或If-Unmodified-Since使用,对比上传修改时间以验证资源是否需要更新。

4. Etag为数字签名,配合If-Match或If-Non-Match使用,对比资源的签名判断是否使用缓存。

 

博主例子

服务器运行截图如下:

这个是回正常的200的HTTP数据包;

这样是回304读取本地缓存的包,

先把他调到正常会HTTP包;

浏览器数据如下:

这里看看其大小:

当变为回304时:

发现大小改变了:

但文本内容还是没变:

看看数据包详细信息:‘

程序结构如下:

源码如下:

widget.h

#ifndef WIDGET_H#define WIDGET_H#include 
QT_BEGIN_NAMESPACEclass QTcpServer;class QTcpSocket;QT_END_NAMESPACEnamespace Ui {class Widget;}class Widget : public QWidget{ Q_OBJECTpublic: Widget(QWidget *parent = 0); ~Widget();protected slots: void newConnectionSlot80(); void errorStringSlot80(); void sendMsg80(); void btnClicked();private: Ui::Widget *ui; QTcpServer *m_tcpServer80; QTcpSocket *m_tcpSocket80;};#endif // WIDGET_H

main.cpp

#include "widget.h"#include 
int main(int argc, char *argv[]){ QApplication a(argc, argv); Widget w; w.show(); return a.exec();}

widget.cpp

#include "widget.h"#include "ui_widget.h"#include 
#include
#include
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ ui->setupUi(this); m_tcpServer80 = new QTcpServer(this); m_tcpServer80->listen(QHostAddress::Any, 80); connect(m_tcpServer80, SIGNAL(newConnection()), this, SLOT(newConnectionSlot80())); connect(m_tcpServer80, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(errorStringSlot80())); connect(ui->pushButton, SIGNAL(clicked(bool)), this, SLOT(btnClicked()));}Widget::~Widget(){ delete ui; m_tcpServer80->close();}void Widget::newConnectionSlot80(){ qDebug() << "newConnectionSlot80() called"; m_tcpSocket80 = m_tcpServer80->nextPendingConnection(); sendMsg80(); //connect(m_tcpSocket80, SIGNAL(readyRead()), this, SLOT(sendMsg80())); //connect(m_tcpSocket80, SIGNAL(connected()), this, SLOT(sendMsg80()));}void Widget::errorStringSlot80(){ qDebug() << m_tcpServer80->errorString();}void Widget::sendMsg80(){ QString contentStr; QString str; if(ui->pushButton->text() == "正常回HTTP包"){ contentStr = "" "" "
" "Socket 80" "" "" "" "

Socket 80

" "" ""; //send msg str = "HTTP/1.1 200 OK\r\n"; str.append("Server:nginx\r\n"); str.append("Content-Type:text/html\r\n"); str.append("Access-Control-Allow-Origin: *\r\n"); str.append("Connection:keep-alive\r\n"); str.append("Cache-Control: max-age=200000\r\n"); str.append("Last-Modified: 777777\r\n"); str.append("Etage: 888888\r\n"); str.append(QString("Content-Length:%1\r\n\r\n").arg(contentStr.size())); str.append(contentStr); //qDebug() << str; } else{ str = "HTTP/1.1 304 OK\r\n"; str.append("Server:nginx\r\n"); str.append("Content-Type:text/html\r\n"); str.append("Access-Control-Allow-Origin: *\r\n"); str.append("Connection:keep-alive\r\n"); str.append("Cache-Control: max-age=200000, no-cache\r\n"); str.append("Last-Modified: 777777\r\n"); str.append("Etage: 888888\r\n"); str.append(QString("Content-Length:%1\r\n\r\n").arg(contentStr.size())); } m_tcpSocket80->write(str.toStdString().c_str());}void Widget::btnClicked(){ if(ui->pushButton->text() == "正常回HTTP包"){ ui->pushButton->setText("回304包"); } else{ ui->pushButton->setText("正常回HTTP包"); }}

 

源码打包下载地址:

转载地址:https://it1995.blog.csdn.net/article/details/89703496 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:HTTP之Cookie和Session(C++ Qt框架实现)
下一篇:Qt文档阅读笔记-FileDialog QML Type官方解析与实例

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月07日 21时41分41秒