用QTJSON、curl与QTSQL、tufao来实现客户端与服务端间通信
2017-07-15 19:43
585 查看
1.开发平台:linux系统上的qt与vim
2.需求:现要实现客户端与服务端之间的通信;服务端采用tufao开源库来作为服务器,同时在服务器上建立一个数据库(采用关系型数据库mysql),用来存储客户端的数据;客户端采用libcurl开源库来发送用户的数据到服务器中,而中间数据包采用json来进行打包,前面的几篇博客已说明json的作用,因此这里不再叙述json的作用;QT很完美的支持了mysql类和json类,因此用qsql来实现数据库的连接和操作,用qjson来打包数据;
3.基本通信模型图如下:
4. qt建立一个项目名为Car,该工程下的所有类或文件如下:
(1)其中Server类继承自QObject类,各文件的源代码为:
Car.pro************************************* Car.pro ************************************* SOURCES += \ main.cpp \ server.cpp HEADERS += \ server.h QT += sql network CONFIG += C++11 LIBS += -ltufao1
main.cpp
************************************* main.cpp ************************************* #include<QCoreApplication> #include"server.h" int main(int argc,char **argv) { QCoreApplication app(argc,argv); new Server; return app.exec(); }
server.h
************************************* server.h ************************************* #ifndef SERVER_H #define SERVER_H #include <QObject> #include<QString> #include<QJsonArray> #include<QJsonObject> #include<QJsonValue> #include<QJsonDocument> #include<tufao-1/Tufao/HttpServer> #include<tufao-1/Tufao/HttpServerRequest> #include<tufao-1/Tufao/HttpServerResponse> #include<QtSql/QSqlDatabase> #include<QtSql/QSqlError> #include<QtSql/QSqlQuery> #include<QtSql/QSqlQuery> using namespace Tufao; class Server : public QObject { Q_OBJECT public: explicit Server(QObject *parent = 0); QSqlDatabase db; HttpServer server; QString md5(QString str); QJsonObject login(const QJsonObject& req); QJsonObject reg(const QJsonObject& req); void onPostReady(HttpServerRequest& request, HttpServerResponse& response); signals: public slots: void onRequestReady(Tufao::HttpServerRequest& request, Tufao::HttpServerResponse& response); }; #endif // SERVER_H
server.c
************************************* server.cpp ************************************* #include "server.h" #include<QByteArray> #include<QCryptographicHash> Server::Server(QObject *parent) : QObject(parent) { /* 创建并打开一个或多个数据库连接 * addDatabase()的"QMYSQL"参数指定用于连接的数据库驱动程序的类型 */ db = QSqlDatabase::addDatabase("QMYSQL"); /* 创建连接对象,打开它以供使用 */ /* 初始化一些连接信息 */ db.setHostName("127.0.0.1"); /* 初始化主机名信息 */ db.setDatabaseName("Car"); /* 初始化数据库名称信息 */ db.setUserName("root"); /* 初始化用户名信息 */ /* 注意下面密码那里填入你自己的数据库的密码 */ db.setPassword("密码"); /* 初始化密码信息 */ /*在初始化这些连接之后,为每个连接建立实时连接,打开(), * 如果open()失败,则返回false。在这种情况下,调用 * QSqlDatabase :: lastError()来获取错误信息。 */ if(! db.open()) { exit(1); } server.listen(QHostAddress::Any,8888); connect(&server,SIGNAL(requestReady(Tufao::HttpServerRequest&, Tufao::HttpServerResponse&)), this,SLOT(onRequestReady(Tufao::HttpServerRequest&, Tufao::HttpServerResponse&))); } QString Server::md5(QString str) { QByteArray db; db = QCryptographicHash::hash(str.toUtf8(),QCryptographicHash::Md5 ); return db.toHex(); } QJsonObject Server::login(const QJsonObject &req) { QJsonObject jsonObj; /* 封装JSON对象 */ QString username = req.value("username").toString(); QString password = req.value("password").toString(); QString md5Password = md5(password); /* MD5加密 */ QString sql = QString("select * from People where username = '%1' and password = '%2'") .arg(username,md5Password); /* QSqlQuery 执行和操作SQL语句的方法;数据库交互通过使用QSqlQuery类实现, * 要执行一个SQL语句,只需创建一个QSqlQuery对象并调用如下所示的QSqlQuery :: exec(); */ QSqlQuery query = db.exec(sql); /* QSqlQuery构造接受可选QSqlDatabase对象,指定要使用的数据库连接。在上面的代码中 * 没有指定任何连接,因此使用默认连接。如果发生错误,exec()返回false。然后,该错误 * 可用作QSqlQuery :: lastError() */ if(query.lastError().type() != QSqlError::NoError) { /* 迭代器 QJsonObject :: insert(const QString& key,const QJsonValue& value) */ jsonObj.insert("result",QString("error")); jsonObj.insert("reason",QString("Add user error")); } /* 返回结果的大小(返回的行数) */ if(query.size() != 1) { jsonObj.insert("result",QString("error")); jsonObj.insert("result",QString("username or password error.")); return jsonObj; } jsonObj.insert("result",QString("ok")); return jsonObj; } QJsonObject Server::reg(const QJsonObject &req) { QJsonObject jsonObj; QString username = req.value("username").toString(); QString password = req.value("password").toString(); QString md5Password = md5(password); QString sql = QString("insert into People(username,password) values('%1','%2')") .arg(username,md5Password); QSqlQuery query = db.exec(sql); if(query.lastError().type() != QSqlError::NoError) { jsonObj.insert("result",QString("error")); jsonObj.insert("reason",QString("add user error")); return jsonObj; } jsonObj.insert("result",QString("ok")); return jsonObj; } void Server::onPostReady(HttpServerRequest &request, HttpServerResponse &response) { /* recv POST data */ QByteArray byte = request.readBody(); #if 0 data is JSON format packet { cmd: login, username: tom, password: xxx } #endif /* QJsonDocument类提供一种方法来读取和写入JSON文档;QJsonDocument是一个包装 * 一个完整的JSON文档的类,可以从基于UTF-8编码的基于文本的表示形式以及Qt自己的 * 二进制格式读取和写入该文档 */ QJsonDocument docu = QJsonDocument::fromJson(byte); /* QJsonObject类封装JSON对象。JSON对象是键值对的列表,其中键是唯一字符串,值 * 由QJsonValue表示。QJsonObject可以被转换和从QVariantMap。您可以使用size(), * insert()和remove()项查询(key,value)对的数量,并使用标准C ++迭代器模 * 式对其内容进行迭代。QJsonObject是一个隐式共享的类,并且只要没有被修改就与它创 * 建的文档共享数据。您可以通过QJsonDocument将对象转换为基于文本的JSON 。 */ /* QJsonObject QJsonDocument :: object()const返回文档中包含的QJsonObject。 * 如果文档包含一个数组,则返回一个空对象。*/ QJsonObject jsonObj = docu.object(); QJsonObject resp; /* QJsonValue QJsonObject :: value(const QString& key)const * 返回QJsonValue表示该键的值的关键。*/ QString cmd = jsonObj.value("cmd").toString(); if(cmd == "register") { resp = reg(jsonObj); } else if(cmd == "login") { resp = login(jsonObj); } else { resp.insert("result",QString("error")); resp.insert("reason",QString("unknow command")); } /* resp ----> QByteArray */ { QJsonDocument docu(resp); QByteArray byte = docu.toJson(); response.end(byte); /* send ---->client */ } } void Server::onRequestReady(Tufao::HttpServerRequest &request, Tufao::HttpServerResponse &response) { response.writeHead(HttpResponseStatus::OK); if(request.method()!= "POST") { response.end("not POST error"); return; } /* if post, wait data upload */ connect(&request,&HttpServerRequest::end, [&](){ onPostReady(request, response); }); } #if 0 void Server::onRequestReady(Tufao::HttpServerRequest& request, Tufao::HttpServerResponse& response) { response.writeHead(HttpResponseStatus::OK); if(request.method()!= "POST") { response.end("not POST error"); return; } /* if post, wait data upload */ connect(&request,&HttpServerRequest::end, [&](){ onPostReady(request, response); }); } #endif
到这里时,服务端已经完成,为了测试其效果,需要写一个简单的客户端程序来进行验证
5.客户端程序如下:
/************************************************************************* * File Name: client.c * Author: The answer * Function: Other * Mail: 2412799512@qq.com * Created Time: 2017年07月15日 星期六 19时26分47秒 ************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <inttypes.h> #include <curl/curl.h> #include "cJSON.h" int main() { cJSON* root = cJSON_CreateObject(); cJSON_AddStringToObject(root, "cmd", "register"); cJSON_AddStringToObject(root, "username", "lxg"); cJSON_AddStringToObject(root, "password", "lxg"); char* p = cJSON_Print(root); cJSON_Delete(root); CURL* curl = curl_easy_init(); /* IP地址为服务端的地址,改为自己的ip地址便可 */ curl_easy_setopt(curl, CURLOPT_URL, "http://IP地址:8888"); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, p); curl_easy_perform(curl); free(p); curl_easy_cleanup(curl); return 0; }
说明:客户端中发送的一个包(json)为:
{
“cmd”: “register”, /* 注意:这里可以是login,或register */
“username”:”xxx”,
“password”:”yyy”
}
6.分别在两个终端中打开并执行服务端和客户端;如下:
客户端的结果为:
这是可以看到服务器中的数据库里面已经有了内容,如下:
一开始数据库是为空的;
相关文章推荐
- Android手机客户端通过JSP实现与Tomcat服务器端通信(Msql数据库,Json作为载体)--服务端代码
- 客户端与服务端的TCP通信实现(Qt)
- Socket实现服务端与客户端通信
- 基于Delphi实现客户端服务端通信Demo
- 使用socket实现简单的客户端和服务端通信(C#语言)
- android使用JSON进行网络数据交换(服务端、客户端)的实现
- 写一个Tomcat+Okhttp实现的聊天websocket聊天框架(一)-- 完成客户端和服务端的通信
- Android 客户端从服务端获取json数据并解析的实现代码
- SilverLight企业应用框架设计【五】客户端调用服务端(使用JSON传递数据,自己实现RESTful Web服务)
- Android BLE与终端通信(三)——客户端与服务端通信过程以及实现
- android使用JSON进行网络数据交换(服务端、客户端)的实现
- Android作为客户端,PC作为服务端:实现网络通信
- Flex使用BlazerDS实现客户端与服务端通信
- Java-Soket实现客户端与服务端双向通信
- socket编程 -- epoll模型服务端/客户端通信的实现
- 流式套接字实现简单的客户端/服务端通信过程
- NIO实现的简单的客户端与服务端通信(非阻塞)
- golang使用net库实现一个简单的服务端和客户端通信
- java实现服务端守护进程来监听客户端通过上传json文件写数据到hbase中
- 用PHP的socket实现客户端到服务端的通信