服务器代码如下:
QtHttpForS.h
#pragma once
#include
#include "ui_QtHttpForS.h"
QT_BEGIN_NAMESPACE
class QTcpServer;
class QTcpSocket;
QT_END_NAMESPACE
class QtHttpForS : public QWidget
{
Q_OBJECT
public:
QtHttpForS(QWidget *parent = Q_NULLPTR);
~QtHttpForS();
int SumNums(QVector nums);
protected slots:
void newConnectionSlot();
void errorStringSlot();
void sendMsg();
private:
Ui::QtHttpForSClass ui;
QTcpServer *m_tcpServer;
QTcpSocket *m_tcpSocket;
QString m_SocketInfo;
};
QtHttpForS.cpp
#include "QtHttpForS.h"
#include
#include
#include
#include
#include
#include "QAbstractSocket"
#include "QStringList"
QtHttpForS::QtHttpForS(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
m_tcpServer = new QTcpServer(this);
m_tcpServer->listen(QHostAddress::Any, 8080);
connect(m_tcpServer, SIGNAL(newConnection()), this, SLOT(newConnectionSlot()));
connect(m_tcpServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(errorStringSlot()));
}
QtHttpForS::~QtHttpForS()
{
m_tcpServer->close();
}
void QtHttpForS::newConnectionSlot()
{
ui.textEdit->append("newConnectionSlot() called!");
m_tcpSocket = m_tcpServer->nextPendingConnection();
connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(sendMsg()));
}
void QtHttpForS::errorStringSlot()
{
ui.textEdit->append(m_tcpServer->errorString());
//qDebug() << m_tcpServer->errorString();
}
void QtHttpForS::sendMsg()
{
QByteArray data = m_tcpSocket->readAll();
QString m_requestInfo = data;
m_SocketInfo += m_requestInfo;
if (m_requestInfo.indexOf("=")>0)
{
ui.textEdit->append(m_SocketInfo);
//qDebug() << m_requestInfo;
QStringList list = m_SocketInfo.split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
qDebug() << list;
if (!list.empty())
{
QStringList headlist = QString(list[0]).split(QRegExp("[ ]"));
QString m_requestMethod = headlist[0];
//ui.textEdit->append(m_requestMethod);
//qDebug() << m_requestMethod;
QStringList paramList;
QString params(headlist[1]);
if (QString(headlist[1]).size()>1)
{
paramList = QString(headlist[1]).split("/");
params = paramList[1];
}
if (m_requestMethod == "GET" && params[0] == '?')
{
params = params.mid(1);
QStringList numsList = params.split('&');
QVector nums;
foreach(QString s, numsList) {
nums.append(s.split('=')[1].toInt());
};
qDebug() << nums;
int sum = SumNums(nums);
QString contentStr = ""
""
""
"Hello"
" "
""
""
"" + QString::number(sum) +
"
"
""
"";
//send msg
QString str = "HTTP/1.1 200 OK\r\n";
str.append("Server:nginx\r\n");
str.append("Content-Type:text/html;charset=UTF-8\r\n");
str.append("Connection:keep-alive\r\n");
str.append(QString("Content-Length:%1\r\n\r\n").arg(contentStr.size()));
str.append(contentStr);
m_tcpSocket->write(str.toStdString().c_str());
}
if (m_requestMethod == "POST")
{
if (params[0] == '?')
{
params = params.mid(1);
QStringList numsList = params.split('&');
QVector nums;
foreach(QString s, numsList) {
nums.append(s.split('=')[1].toInt());
};
qDebug() << nums;
int sum = SumNums(nums);
QJsonObject res;
res.insert("sum", QJsonValue(sum));
QJsonDocument documentJson(res);
QString strJson(documentJson.toJson(QJsonDocument::Compact));
QByteArray dataArray = documentJson.toJson();
//send msg
QString str = "HTTP/1.1 200 OK\r\n";
str.append("Server:nginx\r\n");
str.append("Content-Type:application/json;charset=UTF-8\r\n");
str.append("Connection:keep-alive\r\n");
str.append(QString("Content-Length:%1\r\n\r\n").arg(strJson.size()));
str.append(strJson);
m_tcpSocket->write(str.toStdString().c_str());
}
else
{
params = list[list.size()-1];
QStringList numsList = params.split('&');
QVector nums;
foreach(QString s, numsList) {
nums.append(s.split('=')[1].toInt());
};
qDebug() << nums;
int sum = SumNums(nums);
QJsonObject res;
res.insert("sum", QJsonValue(sum));
QJsonDocument documentJson(res);
QString strJson(documentJson.toJson(QJsonDocument::Compact));
QByteArray dataArray = documentJson.toJson();
//send msg
QString str = "HTTP/1.1 200 OK\r\n";
str.append("Server:nginx\r\n");
str.append("Content-Type:application/json;charset=UTF-8\r\n");
str.append("Connection:keep-alive\r\n");
str.append(QString("Content-Length:%1\r\n\r\n").arg(strJson.size()));
str.append(strJson);
m_tcpSocket->write(str.toStdString().c_str());
}
}
}
m_SocketInfo = "";
}
}
int QtHttpForS::SumNums(QVector nums)
{
int res = 0;
foreach(int num, nums) {
res += num;
};
return res;
}
main.cpp
#include "QtHttpForS.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtHttpForS w;
w.show();
return a.exec();
}
QtHttpForS.ui
QtHttpForSClass
0
0
600
400
QtHttpForS
-
客户端代码:
QtHttpForC.h
#pragma once
#include
#include "ui_QtHttpForC.h"
#include
class QtHttpForC : public QWidget
{
Q_OBJECT
public:
QtHttpForC(QWidget *parent = Q_NULLPTR);
~QtHttpForC();
private slots:
void on_pushButton_clicked();
private:
QButtonGroup *m_Buttongroup;
QTcpSocket *m_Socket;
private:
Ui::QtHttpForCClass ui;
};
QtHttpForC.cpp
#include "QtHttpForC.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "QByteArray"
QtHttpForC::QtHttpForC(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
m_Buttongroup = new QButtonGroup(this);
m_Buttongroup->addButton(ui.radioButton, 1);
m_Buttongroup->addButton(ui.radioButton_2, 2);
ui.textEdit_addr->setText("127.0.0.1");
ui.textEdit_port->setText("8080");
m_Socket = new QTcpSocket();
}
QtHttpForC::~QtHttpForC()
{
}
void QtHttpForC::on_pushButton_clicked()
{
m_Socket->abort();
qDebug() << "Connetting....";
QNetworkRequest request;
QString scheme = "http";
QString serverAddr = ui.textEdit_addr->toPlainText();
QString port = ui.textEdit_port->toPlainText();
QString requestHeader = scheme + QString("://") + serverAddr + QString(":") + port;
if (m_Buttongroup->checkedId() == 1)
{
//获取对应的参数数据
QByteArray data;
data.append("a=");
data.append(ui.textEdit_parm_1->toPlainText().toUtf8());
data.append("&b=");
data.append(ui.textEdit_parm_2->toPlainText().toUtf8());
QNetworkAccessManager manager;
request.setUrl(QUrl(requestHeader));
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));
QNetworkReply *reply = manager.post(request, data);
QEventLoop eventLoop;
QObject::connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
//对请求的返回异常进行处理
QByteArray replyData = reply->readAll();
if (reply->error() != QNetworkReply::NoError) {
qDebug() << reply->error();
delete m_Socket;
}
ui.textEdit_res->setText(QString(replyData));
reply->deleteLater();
}
else
{
QString fullRequest = requestHeader + QString("/?a=%1&b=%2").arg(ui.textEdit_parm_1->toPlainText().toInt()).arg(ui.textEdit_parm_2->toPlainText().toInt());
request.setUrl(QUrl(fullRequest));
QNetworkAccessManager manager;
QNetworkReply *reply = manager.get(request);
QEventLoop eventLoop;
QObject::connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
//对请求的返回异常进行处理
if (reply->error() != QNetworkReply::NoError) {
qDebug() << reply->error();
delete m_Socket;
}
QByteArray replyData = reply->readAll();
ui.textEdit_res->setText(QString(replyData));
reply->deleteLater();
}
}
mian.cpp
#include "QtHttpForC.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtHttpForC w;
w.show();
return a.exec();
}
QtHttpForC.ui
QtHttpForCClass
0
0
600
400
QtHttpForC
-
16777215
80
-
-
服务器地址:
-
10000
30
-
120
16777215
-
30
16777215
端口:
-
50
30
-
80
16777215
-
POST
-
GET
-
300
500
发送请求
false
-
16777215
80
-
300
16777215
-
50
16777215
参数1:
-
100
50
-
300
70
-
50
16777215
参数2:
-
100
50
-
程序运行效果:
GET请求:
POST请求:
POST请求使用postman测试:
注意:可以发现,在使用postman进行POST请求发送时,服务器接收到的请求头与QTSocket的POST请求的请求头是不同的,这里的原因目前还没有想到很好的解释。其中QTSocket的请求是将所有的参数组合后放在了请求头的最后,所以程序中在进行POST解析时多了一种情况的解析。
另外服务端在接收请求时,使用readRedy()信号,会出现因为数据大小而导致的粘包,即客户端发送的请求,会触发一次或多次的readRedy()信号,这时就需要考虑判定服务器所接收的rely->readAll()是不是完整的。本例中主要用到的方法是根据info中是否包含”=“来确定的。
TODO:
当然更为健壮的一种方式应该是通过字节数来确定,请求是否完整。
需要考虑的是如何处理多线程,多请求异步发生。