QT实现客户端服务器HTTP(get请求、post请求)

服务器代码如下:

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请求:

QT实现客户端服务器HTTP(get请求、post请求)_第1张图片

POST请求:

QT实现客户端服务器HTTP(get请求、post请求)_第2张图片

POST请求使用postman测试:

QT实现客户端服务器HTTP(get请求、post请求)_第3张图片

注意:可以发现,在使用postman进行POST请求发送时,服务器接收到的请求头与QTSocket的POST请求的请求头是不同的,这里的原因目前还没有想到很好的解释。其中QTSocket的请求是将所有的参数组合后放在了请求头的最后,所以程序中在进行POST解析时多了一种情况的解析。

另外服务端在接收请求时,使用readRedy()信号,会出现因为数据大小而导致的粘包,即客户端发送的请求,会触发一次或多次的readRedy()信号,这时就需要考虑判定服务器所接收的rely->readAll()是不是完整的。本例中主要用到的方法是根据info中是否包含”=“来确定的。

TODO:

当然更为健壮的一种方式应该是通过字节数来确定,请求是否完整。

需要考虑的是如何处理多线程,多请求异步发生。

你可能感兴趣的:(QT网络编程,qt,http,c++)