一、搭建apache服务器
在这之前需要先在Linux上搭建apache服务器,用于QT实现的程序与Linux之间进行http通信
搭建流程可以参考我之前的博客:
如何在Linux上搭建apahce服务器https://blog.csdn.net/takashi77/article/details/109492193
二、相关知识点
主要使用的几个QT网络相关的类(注意需要先在.pro工程文件中添加network
模块,才能使用网络模块的)
1、QNetworkRequest:通过传递一个Url网络地址进行网络请求,也保存网络请求的信息
2、NetworkAccessManager:用于协调网络操作;在进行
post/get
发送请求后会创建一个网络回复的返回的(需要使用一个QNetworkReply 对象的指针
接收发送请求后创建的对象)
3、QNetworkReply:它是QIODevice的子类,支持流读写功能,也支持异步或同步工作;用于网络回复的相关操作;当有数据回复时会发送一个
readyRead()信号
apache相关
1、apache中cgi程序中获取客户端通过get请求发送的数据环境变量为:
QUERY_STRING
,可通过该环境变量直接获得发送的数据
2、apache中cgi程序想获取客户端通过post请求发送过来的数据是不能直接拿到数据的,需要先通过
CONTENT_LENGTH
这个环境变量拿到数据的长度,然后再通过系统的标准输入
拿到数据
三、代码实现
1、QT端程序
MainWindow.h文件
#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected slots:
void ReadData();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::MainWindow *ui;
QNetworkAccessManager mannger; //通过发送post请求与get请求的对象
QNetworkReply *reply; //因为QNetworkReply中有未实现的虚函数是一个抽象类,因此需要创建指针,然后接收
// QNetworkAccessManager中的post或者get请求返回的QNetworkReply指针
QByteArray array; //接收返回的数据
};
#endif // MAINWINDOW_H
MainWindow.cpp文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
delete reply;
}
//发送post请求
void MainWindow::on_pushButton_clicked()
{
QUrl url("http://192.168.19.118/cgi-bin/CsdnPost.cgi");
QNetworkRequest request(url); //发送请求的地址
request.setHeader(QNetworkRequest::ContentTypeHeader,"multipart/form-data");
reply = mannger.post(request,"helloPost"); //发送的内容为helloworld
//当有数据到达时响应
connect(reply,&QNetworkReply::readyRead,this,&MainWindow::ReadData);
}
//发送get请求
void MainWindow::on_pushButton_2_clicked()
{
QUrl url("http://192.168.19.118/cgi-bin/CsdnGet.cgi?helloGet");
QNetworkRequest request(url);
reply = mannger.get(request);
//当有数据到达时响应
connect(reply,&QNetworkReply::readyRead,this,&MainWindow::ReadData);
}
//当接收到有数据返回时,响应此函数
void MainWindow::ReadData()
{
QByteArray data = reply->readAll();
array.append(data);//追加到array
ui->textEdit->setText(array); //显示再屏幕上
}
main.cpp文件
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
2、Linux端程序
注意因为这里使用的是http去调用Linux下的cgi(Common Gateway Interface)
程序实现的通信交流,因此这里需要去到搭建的apache服务器下的cgi-bin
路径下进行编写程序(开头博文里面有介绍),否则会调用不,cgi程序其实就是使用gcc编译c语言编写的程序;
(注意:编译后的cgi程序名需要与发起请求时指定的cgi程序名一致,否则会导致调用不成功!!)
CsdnPost.c文件
#include <string.h>
#include <unistd.h>
int main()
{
//告诉客户端实际返回的内容的内容类型
printf("Content-type:text/html;charset=utf-8\n\n");
//post请求是通过CONTENT_LENGTH关键字获取数据长度再从标准输入读取数据的
char *p = getenv("CONTENT_LENGTH");
if(p==NULL)
{
printf("receive error");
return -1;
}
int length = atoi(p); //字符转整数
char buffer[length+1]; //定义接收数据的数据,预留一位给结束符
memset(buffer,0,sizeof(buffer));
fread(buffer,sizeof(buffer),1,stdin);//读取数据
printf("%s\n",buffer); //返回给客户端
return 0;
}
CsdnGet.c文件
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Content-type:text/html;charset=utf-8\n\n"); //cgi--http
//get请求从QUERY_STRING关键字读取数据
char *p = getenv("QUERY_STRING");
if(p==NULL)
{
printf("receive error");
return -1;
}
printf("%s\n",p);
return 0;
}