跳到主要内容

网络编程

Qt 提供了强大的网络编程支持,包括 HTTP 请求、TCP/UDP 通信等功能。

QNetworkAccessManager(HTTP 请求)

用于发送 HTTP 请求和处理响应。

GET 请求

#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>

class HttpClient : public QObject
{
Q_OBJECT

public:
HttpClient(QObject *parent = nullptr) : QObject(parent)
{
manager = new QNetworkAccessManager(this);
}

void get(const QString &url)
{
QNetworkRequest request(QUrl(url));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

QNetworkReply *reply = manager->get(request);

connect(reply, &QNetworkReply::finished, this, [=]() {
if (reply->error() == QNetworkReply::NoError) {
QByteArray data = reply->readAll();
QString text = QString::fromUtf8(data);
qDebug() << "响应:" << text;
} else {
qDebug() << "错误:" << reply->errorString();
}
reply->deleteLater();
});
}

private:
QNetworkAccessManager *manager;
};

POST 请求

void post(const QString &url, const QJsonObject &json)
{
QNetworkRequest request(QUrl(url));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

QJsonDocument doc(json);
QByteArray data = doc.toJson();

QNetworkReply *reply = manager->post(request, data);

connect(reply, &QNetworkReply::finished, this, [=]() {
if (reply->error() == QNetworkReply::NoError) {
QByteArray response = reply->readAll();
QJsonDocument doc = QJsonDocument::fromJson(response);
QJsonObject obj = doc.object();
// 处理响应
}
reply->deleteLater();
});
}

// 使用示例
QJsonObject json;
json["username"] = "admin";
json["password"] = "123456";
post("https://api.example.com/login", json);

文件下载

void downloadFile(const QString &url, const QString &savePath)
{
QNetworkRequest request(QUrl(url));
QNetworkReply *reply = manager->get(request);

QFile *file = new QFile(savePath);
if (!file->open(QIODevice::WriteOnly)) {
delete file;
return;
}

connect(reply, &QNetworkReply::readyRead, this, [=]() {
file->write(reply->readAll());
});

connect(reply, &QNetworkReply::finished, this, [=]() {
file->close();
delete file;
reply->deleteLater();

if (reply->error() == QNetworkReply::NoError) {
qDebug() << "下载完成";
}
});

// 下载进度
connect(reply, &QNetworkReply::downloadProgress, this,
[=](qint64 bytesReceived, qint64 bytesTotal) {
if (bytesTotal > 0) {
int percent = static_cast<int>((bytesReceived * 100) / bytesTotal);
qDebug() << "下载进度:" << percent << "%";
}
});
}

QTcpSocket(TCP 客户端)

#include <QTcpSocket>

class TcpClient : public QObject
{
Q_OBJECT

public:
TcpClient(QObject *parent = nullptr) : QObject(parent)
{
socket = new QTcpSocket(this);

connect(socket, &QTcpSocket::connected, this, [=]() {
qDebug() << "已连接到服务器";
});

connect(socket, &QTcpSocket::disconnected, this, [=]() {
qDebug() << "与服务器断开连接";
});

connect(socket, &QTcpSocket::readyRead, this, [=]() {
QByteArray data = socket->readAll();
qDebug() << "收到数据:" << data;
});

connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),
this, [=](QAbstractSocket::SocketError error) {
qDebug() << "错误:" << socket->errorString();
});
}

void connectToHost(const QString &host, quint16 port)
{
socket->connectToHost(host, port);
}

void send(const QByteArray &data)
{
if (socket->state() == QAbstractSocket::ConnectedState) {
socket->write(data);
}
}

void disconnect()
{
socket->disconnectFromHost();
}

private:
QTcpSocket *socket;
};

QTcpServer(TCP 服务器)

#include <QTcpServer>
#include <QTcpSocket>

class TcpServer : public QObject
{
Q_OBJECT

public:
TcpServer(QObject *parent = nullptr) : QObject(parent)
{
server = new QTcpServer(this);

connect(server, &QTcpServer::newConnection, this, [=]() {
QTcpSocket *client = server->nextPendingConnection();
clients.append(client);

qDebug() << "新客户端连接:" << client->peerAddress().toString();

connect(client, &QTcpSocket::readyRead, this, [=]() {
QByteArray data = client->readAll();
qDebug() << "收到:" << data;
// 广播给所有客户端
broadcast(data, client);
});

connect(client, &QTcpSocket::disconnected, this, [=]() {
qDebug() << "客户端断开";
clients.removeAll(client);
client->deleteLater();
});
});
}

bool start(quint16 port)
{
return server->listen(QHostAddress::Any, port);
}

void broadcast(const QByteArray &data, QTcpSocket *except = nullptr)
{
for (QTcpSocket *client : clients) {
if (client != except && client->state() == QAbstractSocket::ConnectedState) {
client->write(data);
}
}
}

private:
QTcpServer *server;
QList<QTcpSocket*> clients;
};

QUdpSocket(UDP 通信)

#include <QUdpSocket>

class UdpClient : public QObject
{
Q_OBJECT

public:
UdpClient(QObject *parent = nullptr) : QObject(parent)
{
socket = new QUdpSocket(this);
socket->bind(QHostAddress::Any, 12345);

connect(socket, &QUdpSocket::readyRead, this, [=]() {
while (socket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(socket->pendingDatagramSize());
QHostAddress sender;
quint16 port;

socket->readDatagram(datagram.data(), datagram.size(), &sender, &port);
qDebug() << "收到来自" << sender.toString() << ":" << port << "的数据:" << datagram;
}
});
}

void send(const QByteArray &data, const QString &host, quint16 port)
{
socket->writeDatagram(data, QHostAddress(host), port);
}

private:
QUdpSocket *socket;
};

下一步

Qt 网络编程基础已介绍完毕。建议继续深入学习 Qt 的线程编程,以实现高效的网络通信应用。