由于项目需要,需要实现利用QT的写一个HTTP服务器,能够提供本地文件在同一网段中,供设备下载,故此,编写了一个小程序,来实习那该功能。
先看看效果:
在浏览器中输入
http://localhost:8080可查看到界面中出现“你好,世界!”
当我们输入http://localhost:8080
/file时,就可以看到我们可以将我们存放到本地的11.txt文件下下来。
话不多说,直接上代码:
.pro文件
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets network
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
httpserver.cpp
HEADERS += \
httpserver.h
FORMS += \
httpserver.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${T
.h文件
#ifndef HTTPSERVER_H
#define HTTPSERVER_H
#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTextStream>
#include <QDebug>
#include <QFile> // 用于文件操作
QT_BEGIN_NAMESPACE
namespace Ui {
class HttpServer;
}
QT_END_NAMESPACE
class HttpServer : public QTcpServer
{
Q_OBJECT
public:
HttpServer(QWidget *parent = nullptr);
~HttpServer();
void startServer(int port); // 启动服务器,监听指定端口
private slots:
void handleNewConnection(); // 处理新的客户端连接
void handleClientRequest(QTcpSocket *clientSocket); // 处理客户端请求
private:
void sendResponse(QTcpSocket *clientSocket, const QString &response); // 发送响应给客户端
QString readFile(const QString &filePath); // 读取文件内容
private:
Ui::HttpServer *ui;
};
#endif // HTTPSERVER_H
.cpp文件
#include "httpserver.h"
#include "ui_httpserver.h"
HttpServer::HttpServer(QWidget *parent)
: QTcpServer(parent)
, ui(new Ui::HttpServer)
{
//ui->setupUi(this);
// 当有新的连接时,调用handleNewConnection槽
connect(this, &QTcpServer::newConnection, this, &HttpServer::handleNewConnection);
}
HttpServer::~HttpServer()
{
//delete ui;
close(); // 关闭服务器
}
void HttpServer::startServer(int port)
{
if (!listen(QHostAddress::Any, port)) // 监听所有网络接口的指定端口
{
qDebug() << "服务器启动失败!";
}
else
{
qDebug() << "服务器已启动,监听端口:" << port;
}
}
void HttpServer::handleNewConnection()
{
while (hasPendingConnections()) // 检查是否有待处理的连接
{
QTcpSocket *clientSocket = nextPendingConnection(); // 获取新的客户端连接
connect(clientSocket, &QTcpSocket::readyRead, this, [this, clientSocket]() {
handleClientRequest(clientSocket); // 处理客户端请求
});
}
}
void HttpServer::handleClientRequest(QTcpSocket *clientSocket)
{
QTextStream in(clientSocket); // 从客户端读取数据
QString request = in.readAll(); // 读取完整的请求内容
qDebug() << "客户端请求:" << request;
// 解析请求行(第一行)
QStringList requestLines = request.split("\r\n");
QStringList requestLine = requestLines.first().split(" ");
QString method = requestLine[0]; // 请求方法(如GET)
QString path = requestLine[1]; // 请求路径(如/)
qDebug() << "请求方法" << method << "请求路径" << path;
// 根据请求路径构造响应
QString response;
if (method == "GET")
{
if (path == "/") // 请求根路径,返回默认页面
{
response = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=UTF-8\r\n"
"Connection: close\r\n"
"\r\n"
"<html><body><h1>你好,世界!</h1></body></html>";
}
else if (path == "/file") // 请求/file路径,返回文件内容
{
QString filePath = "D:/11.txt"; // 指定文件路径
QString fileContent = readFile(filePath); // 读取文件内容
if (!fileContent.isEmpty()) // 如果文件内容不为空
{
response = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/plain; charset=UTF-8\r\n"
"Connection: close\r\n"
"\r\n"
+ fileContent; // 返回文件内容
}
else
{
// response = "HTTP/1.1 404 Not Found\r\n"
// "Content-Type: text/plain; charset=UTF-8\r\n"
// "Connection: close\r\n"
// "\r\n"
// "文件未找到"; // 文件未找到时返回404
}
}
else // 其他路径返回404
{
response = "HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/plain; charset=UTF-8\r\n"
"Connection: close\r\n"
"\r\n"
"404 Not Found";
}
}
else // 不支持其他HTTP方法
{
response = "HTTP/1.1 405 Method Not Allowed\r\n"
"Content-Type: text/plain; charset=UTF-8\r\n"
"Connection: close\r\n"
"\r\n"
"不支持的请求方法";
}
----------------------------------------------------------*/
//能将数据正常的发送出去,通过HTTP的发送,上传文件
if (method == "GET")
{
if (path == "/") // 请求根路径,返回默认页面
{
response = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=UTF-8\r\n"
"Connection: close\r\n"
"\r\n"
"<html><body><h1>你好,世界!</h1></body></html>";
}
else if (path == "/file") // 请求/file路径,返回文件内容
{
QString filePath = "D:/11.txt"; // 指定文件路径
QString fileContent = readFile(filePath); // 读取文件内容
if (!fileContent.isEmpty()) // 如果文件内容不为空
{
response = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/plain; charset=UTF-8\r\n"
"Content-Disposition: attachment; filename=\"11.txt\"\r\n"
"Connection: close\r\n"
"\r\n"
+ fileContent; // 返回文件内容
}
else
{
// response = "HTTP/1.1 404 Not Found\r\n"
// "Content-Type: text/plain; charset=UTF-8\r\n"
// "Connection: close\r\n"
// "\r\n"
// "文件未找到"; // 文件未找到时返回404
}
}
else // 其他路径返回404
{
response = "HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/plain; charset=UTF-8\r\n"
"Connection: close\r\n"
"\r\n"
"404 Not Found";
}
}
else // 不支持其他HTTP方法
{
response = "HTTP/1.1 405 Method Not Allowed\r\n"
"Content-Type: text/plain; charset=UTF-8\r\n"
"Connection: close\r\n"
"\r\n"
"不支持的请求方法";
}
sendResponse(clientSocket, response); // 发送响应给客户端
}
void HttpServer::sendResponse(QTcpSocket *clientSocket, const QString &response)
{
QTextStream out(clientSocket); // 创建文本流,用于向客户端发送数据
out.setCodec("UTF-8"); // 设置编码为UTF-8,确保中文显示正常
out << response; // 写入响应内容
out.flush(); // 确保数据被发送
clientSocket->disconnectFromHost(); // 主动断开与客户端的连接
// 检查套接字是否已经处于未连接状态
if (clientSocket->state() != QAbstractSocket::UnconnectedState)
{
clientSocket->waitForDisconnected(); // 等待连接断开
}
clientSocket->deleteLater(); // 释放客户端套接字资源
}
QString HttpServer::readFile(const QString &filePath)
{
QFile file(filePath); // 创建文件对象
if (!file.exists()) // 如果文件不存在
{
qDebug() << "文件不存在:" << filePath;
return QString(); // 返回空字符串
}
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) // 打开文件
{
qDebug() << "无法打开文件" << filePath;
return QString(); // 返回空字符串
}
QString content = file.readAll(); // 读取文件内容
file.close(); // 关闭文件
return content; // 返回文件内容
}
main.cpp文件
#include "httpserver.h"
#include <QApplication>
#include "HttpServer.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
HttpServer server; // 创建服务器对象
server.startServer(8080); // 启动服务器,监听8080端口
return a.exec();
}
哈哈哈,进行简单的小修改,将代码补全,也能更好的将代码拷贝复制了。