上传FTP文件
//networkrequestcallback.h
class NetworkRequestCallback : public QObject {
Q_OBJECT
public:
bool success = true;
void reset() {
success = true;
}
public slots:
void onFinish(QNetworkReply* repley) {
if (!success) return;
cout << "Request Done" << endl;
}
void onProgress(qint64 finish, qint64 total) {
if (!success) return;
cout << "Request Finished: " << finish << "/" << total << endl;
}
void onError(QNetworkReply::NetworkError error) {
success = false;
cout << "Request Error " << error << endl;
}
};
//main.cpp
QApplication app(argc, argv);
setlocale(LC_ALL, ".ACP");
QNetworkAccessManager accessManager;
accessManager.setNetworkAccessible(QNetworkAccessManager::Accessible);
QUrl url("ftp://192.168.8.121/upload");
url.setPort(8781);
url.setUserName("root");
url.setPassword("123456");
url.setPath("a.json"); //如果要指定文件夹,将文件夹名拼接在url后面即可
QFile file("C:/1.json");
file.open(QFile::ReadOnly);
//将本地的[1.json]文件上传到服务器上的[upload/a.json]位置
QNetworkRequest request(url);
QNetworkReply* reply = accessManager.put(request, &file);
NetworkRequestCallback callback;
callback.reset();
QObject::connect(&accessManager, SIGNAL(finished(QNetworkReply*)), &callback, SLOT(onFinish(QNetworkReply*)));
QObject::connect(reply, SIGNAL(uploadProgress(qint64, qint64)), &callback, SLOT(onProgress(qint64, qint64)));
QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), &callback, SLOT(onError(QNetworkReply::NetworkError)));
return app.exec();
下载FTP文件
//networkrequestcallback.h
class NetworkRequestCallback : public QObject {
Q_OBJECT
private:
QNetworkReply* reply;
public:
bool success = true;
void reset(QNetworkReply* reply = nullptr) {
this->reply = reply;
success = true;
}
public slots:
void onFinish(QNetworkReply* repley) {
if (!success) return;
cout << "Request Done" << endl;
}
void onProgress(qint64 finish, qint64 total) {
if (!success) return;
cout << "Request Finished: " << finish << "/" << total << endl;
}
void onError(QNetworkReply::NetworkError error) {
success = false;
cout << "Request Error" << error << endl;
}
void onRead() {
QByteArray byteArray = reply->readAll();
QFile file("C:/1.json");
file.open(QFile::ReadWrite);
file.write(byteArray);
qdebug << byteArray << endl;
cout << "Read Byte Stream" << endl;
}
};
//main.cpp
QApplication app(argc, argv);
setlocale(LC_ALL, ".ACP");
QNetworkAccessManager accessManager;
accessManager.setNetworkAccessible(QNetworkAccessManager::Accessible);
QUrl url("ftp://192.168.8.121/upload/a.json");
url.setPort(8781);
url.setUserName("root");
url.setPassword("123456");
//将服务器上的[upload/a.json]文件下载到本地[1.json]位置
QNetworkRequest request(url);
QNetworkReply* reply = accessManager.get(request);
NetworkRequestCallback callback;
callback.reset(reply);
QObject::connect(&accessManager, SIGNAL(finished(QNetworkReply*)), &callback, SLOT(onFinish(QNetworkReply*)));
QObject::connect(reply, SIGNAL(downloadProgress(qint64, qint64)), &callback, SLOT(onProgress(qint64, qint64)));
QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), &callback, SLOT(onError(QNetworkReply::NetworkError)));
QObject::connect(reply, SIGNAL(readyRead()), &callback, SLOT(onRead()));
return app.exec();
发送只有文本参数的Http请求
由于Get请求只有URL,比较简单,不再讲解,这里主要介绍Post请求方式
//networkrequestcallback.h
class NetworkRequestCallback : public QObject {
Q_OBJECT
private:
QNetworkReply* reply;
public:
bool success = true;
void reset(QNetworkReply* reply = nullptr) {
this->reply = reply;
success = true;
}
public slots:
void onError(QNetworkReply::NetworkError status) {
success = false;
cout << "Request Error " << status << endl;
}
void onRead() {
QNetworkReply::NetworkError status = reply->error();
QByteArray byteArray = reply->readAll();
qdebug << status << endl;
qdebug << byteArray << endl;
cout << "Read Byte Stream" << endl;
}
};
//main.cpp
QApplication app(argc, argv);
setlocale(LC_ALL, ".ACP");
//网络请求处理器
QNetworkAccessManager manager;
//设置基本URL
QUrl url("http://192.168.8.121:8001/animal/login");
//设置URL额外参数
QUrlQuery query;
query.addQueryItem("username", "aodun");
url.setQuery(query);
//构建请求
QNetworkRequest request(url);
//设置请求头参数
request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
//设置表单参数
QByteArray formData;
formData.append("&account=").append("aodun");
formData.append("&password=").append("123456");
//执行请求
QNetworkReply* reply = manager.post(request, formData);
//请求结果回调
NetworkRequestCallback callback;
callback.reset(reply);
QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), &callback, SLOT(onError(QNetworkReply::NetworkError)));
QObject::connect(reply, SIGNAL(readyRead()), &callback, SLOT(onRead()));
return app.exec();
发送带文件的Http请求
上面介绍的是URL_ENCODED_POST式的post请求,只有一块RequestBody
RequestBody用一段连续的键值对存放全部文本类型的表单参数
如果要上传文件,须使用MULTI_FORM_POST式的post请求
MULTI_FORM_POST将RequestBody分割为若干块,每个子块既可以存放文本,又可以存放文件
在Qt的网络框架中,QHttpMultiPart代表着顶级Body块,QHttpPart代表着分割后的子Body块
//networkrequestcallback.h
class NetworkRequestCallback : public QObject {
Q_OBJECT
private:
QNetworkReply* reply;
public:
bool success = true;
void reset(QNetworkReply* reply = nullptr) {
this->reply = reply;
success = true;
}
public slots:
void onError(QNetworkReply::NetworkError status) {
success = false;
qdebug << "Network Error: " << status << endl;
}
void onRead() {
qdebug << "Http Response Status: " << reply->error() << endl;
qdebug << "Http Response Body: " << reply->readAll() << endl;
}
};
//main.cpp
QApplication app(argc, argv);
setlocale(LC_ALL, ".ACP");
//网络请求处理器
QNetworkAccessManager manager;
//设置基本URL
QUrl url("http://192.168.8.121:8001/animal/file/upload");
//构建请求
QNetworkRequest request(url);
//设置表单参数
QHttpMultiPart* formData = new QHttpMultiPart(QHttpMultiPart::FormDataType);
//添加文本表单:folder=001
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"folder\"");
textPart.setBody("001");
formData->append(textPart);
//添加文件表单:file=File
QHttpPart filePart;
filePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/png");
filePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"file\"; filename=\"1.png\"");
QFile* file = new QFile("C:/1.png");
file->open(QIODevice::ReadOnly);
file->setParent(formData); //绑定父级对象,Qt在父级对象回收时,会自动回收子级对象
filePart.setBodyDevice(file);
formData->append(filePart);
//执行请求
QNetworkReply* reply = manager.post(request, formData);
//请求结果回调
NetworkRequestCallback callback;
callback.reset(reply);
QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), &callback, SLOT(onError(QNetworkReply::NetworkError)));
QObject::connect(reply, SIGNAL(readyRead()), &callback, SLOT(onRead()));
return app.exec();
下载Http文件
和普通请求一样,通过QNetworkReply.readAll(),就可以获取文件的全部字节,将字节写入文件即可完成下载
void onRead() {
qdebug << "Http Response Status: " << reply->error() << endl;
qdebug << "Http Response Body: " << reply->readAll() << endl;
}
发送RAW格式的Http请求
URL_ENCODED_POST式的post请求,RequestBody用一组键值对来存储若干文本参数
MULTI_FORM_POST式的post请求,RequestBody用若干子Body来分别存储文本或文件
RAW式的post请求,将整段文本直接放入RequestBody中,没有格式要求
这对于复杂类型的请求数据来说,比如JSON,XML,类对象等,非常方便,服务端可以将这些复杂文本数据直接转为对象使用
传统的Http编程中,Form格式比较常用,RAW格式的Http请求比较少见,但随着请求数据越来越复杂,后端数据解析越来越自动化,RAW格式是以后的一个趋势,因为它能力更强大,配合自动化框架使用也极方便
//main.cpp
QApplication app(argc, argv);
setlocale(LC_ALL, ".ACP");
//网络请求处理器
QNetworkAccessManager manager;
//设置基本URL
QUrl url("http://192.168.8.121:8001/animal/test/v1");
//构建请求
QNetworkRequest request(url);
request.setRawHeader("Content-Type", "application/json");
//设置RAW格式请求体数据
QJsonObject jsonObject;
jsonObject.insert("account", "admin");
jsonObject.insert("password", "123456");
QByteArray rawData = QJsonDocument(jsonObject).toJson();
//执行请求
QNetworkReply* reply = manager.post(request, rawData);
//请求结果回调
NetworkRequestCallback callback;
callback.reset(reply);
QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), &callback, SLOT(onError(QNetworkReply::NetworkError)));
QObject::connect(reply, SIGNAL(readyRead()), &callback, SLOT(onRead()));
return app.exec();
这里是一个简单的Json数据,虽然也可以用Form来实现,但是当数据存在多层嵌套时,就无法用Form来实现了,只能用Json、Xml或类对象来表示,然后放到RAW格式的RequestBody中来实现了
我们来看下服务端解析RAW数据有多简单,这里我们以Java的Spring后台为例
//用来接收Json请求参数的类模型
public class LoginRequest {
public String account;
public String password;
}
//自动将Json请求参数转为类对象
@ResponseBody
@RequestMapping(value = "/v1")
public HttpResponseBody login(@RequestBody LoginRequest loginRequest) {
System.out.println(loginRequest.account);
return HttpResponseBody.success("ok");
}
发送Binary格式的Http请求
//main.cpp
//网络请求处理器
QNetworkAccessManager manager;
//设置基本URL
QUrl url("http://192.168.8.121:8001/animal/test/v1");
//构建请求
QNetworkRequest request(url);
request.setRawHeader("Content-Type", "application/octet-stream");
//设置Binary格式请求体数据
QFile file("C:/animal-airport-v1.1.33.1181.apk");
file.open(QFile::ReadWrite);
QByteArray binData = file.readAll();
//执行请求
QNetworkReply* reply = manager.post(request, binData);
//server.java
@ResponseBody
@RequestMapping(value = "/v1")
public HttpResponseBody saveBinaryData(@RequestBody byte[] body, HttpServletRequest request) {
FileUtil.writeToFile("C:/1.apk", body);
return HttpResponseBody.success("ok");
}
使用TcpSocket
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
setlocale(LC_ALL, ".ACP");
QMainWindow* w = new QMainWindow();
w->setGeometry(100, 100, 300, 700);
QLineEdit* clientContentEdit = new QLineEdit(w);
clientContentEdit->setGeometry(0, 0, 300, 100);
QPushButton* clientSendButton = new QPushButton("Send Client Message", w);
clientSendButton->setGeometry(0, 100, 300, 50);
QLineEdit* serverContentEdit = new QLineEdit(w);
serverContentEdit->setGeometry(0, 150, 300, 100);
QPushButton* serverSendButton = new QPushButton("Send Server Message", w);
serverSendButton->setGeometry(0, 250, 300, 50);
QTextEdit* logPrintEdit = new QTextEdit(w);
logPrintEdit->setGeometry(0, 300, 300, 400);
w->show();
//创建Socket服务端
QTcpServer* socketServer = new QTcpServer();
socketServer->listen(QHostAddress::Any, 6666);
//监听客户端连接
QObject::connect(socketServer, &QTcpServer::newConnection, [=]() {
//获取连接的客户端
QTcpSocket* socket = socketServer->nextPendingConnection();
logPrintEdit->append("server: client connected");
//接收客户端消息
QObject::connect(socket, &QTcpSocket::readyRead, [=]() {
QByteArray message = socket->readAll();
logPrintEdit->append("server: receive message");
logPrintEdit->append(message);
});
//向客户端发送消息
QObject::connect(serverSendButton, &QPushButton::clicked, [=](bool) {
socket->write(serverContentEdit->text().toUtf8());
});
});
//创建Socket客户端
QTcpSocket* socketClient = new QTcpSocket();
socketClient->connectToHost("localhost", 6666);
//接收服务端消息
QObject::connect(socketClient, &QTcpSocket::readyRead, [=]() {
QByteArray message = socketClient->readAll();
logPrintEdit->append("client: receive message");
logPrintEdit->append(message);
});
//向服务端发送消息
QObject::connect(clientSendButton, &QPushButton::clicked, [=](bool) {
socketClient->write(clientContentEdit->text().toUtf8());
});
return app.exec();
}
使用UdpSocket
UdpSocket发送的消息分为三类:单播,广播,组播
单播发送给指定设备,广播发送给全部设备,组播发送给一组设备
UdpSocket没有服务端和客户端之分,不用先建立连接,只要地址和端口,就可以收到彼此的消息
广播,组播,本质上也只是一个特殊的网络地址
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
setlocale(LC_ALL, ".ACP");
QTextEdit* consoleEdit = new QTextEdit();
consoleEdit->setGeometry(100, 100, 300, 400);
consoleEdit->show();
//创建UDP发送端
QUdpSocket* sender = new QUdpSocket();
sender->bind(QHostAddress::AnyIPv4, 5555, QUdpSocket::ShareAddress);
sender->joinMulticastGroup(QHostAddress("224.0.0.1"));
QObject::connect(sender, &QUdpSocket::readyRead, [=]() {
while (sender->hasPendingDatagrams()) {
//接收回复数据
QNetworkDatagram datagram = sender->receiveDatagram();
consoleEdit->append("sender: got message");
consoleEdit->append(datagram.data());
}
});
//创建UDP接收端
QUdpSocket* receiver = new QUdpSocket();
receiver->bind(QHostAddress::AnyIPv4, 6666, QUdpSocket::ShareAddress);
receiver->joinMulticastGroup(QHostAddress("224.0.0.1"));
QObject::connect(receiver, &QUdpSocket::readyRead, [=]() {
while (receiver->hasPendingDatagrams()) {
//接收数据
QNetworkDatagram datagram = receiver->receiveDatagram();
consoleEdit->append("receiver: got message");
consoleEdit->append(datagram.data());
//回复数据
QByteArray reply = "i got message";
receiver->writeDatagram(reply.data(), reply.size(), datagram.senderAddress(), datagram.senderPort());
}
});
//发送UDP单播消息
QByteArray d1 = "single broadcast";
sender->writeDatagram(d1.data(), d1.size(), QHostAddress::LocalHost, 6666);
//发送UDP广播消息
QByteArray d2 = "wide broadcast";
sender->writeDatagram(d2.data(), d2.size(), QHostAddress::Broadcast, 6666);
//发送UDP组播消息
QByteArray d3 = "group broadcast";
sender->writeDatagram(d3.data(), d3.size(), QHostAddress("224.0.0.1"), 6666);
return app.exec();
}
使用Https
Qt默认是不支持Https的,需要手动安装OpenSSL支持库,可以通过以下链接下载
直接将对应版本的dll拷贝exe所在文件夹下面即可
https://download.csdn.net/download/u013718730/12066513