1 libhv和mysql
libhv是一个跨平台的C++网络库。
mysql是一个关系型数据库。
2 下载MySQL,
最好不要下载高版本的,容易出错!!!
下载地址MySQL
下载好后目录是这样的:
然后在环境变量里配置:
验证,打开cmd窗口,输入mysql --version
3 C++里集成mysql和libhv
用的是visual studio,我下载的Mysql和libhv都是64位的,
模板:
#include "router.h"
#include "handler.h"
#include "hv/hthread.h"
#include "hv/hasync.h" // import hv::async
#include "hv/requests.h" // import requests::async
Router::Router()
{
}
Router::~Router()
{
}
void Router::Register(hv::HttpService& router) {
// preprocessor => Handler => postprocessor
router.preprocessor = Handler::preprocessor;
router.postprocessor = Handler::postprocessor;
// router.errorHandler = Handler::errorHandler;
// router.largeFileHandler = Handler::sendLargeFile;
// router.POST("/dev", [](const HttpContextPtr& ctx) {
// // demo演示丢到hv::async全局线程池处理,实际使用推荐丢到自己的消费者线程/线程池
// hv::async([ctx]() {
// ctx->send(ctx->body(), ctx->type());
// });
// return 0;
// });
// curl -v http://ip:port/login -H "Content-Type:application/json" -d '{"username":"admin","password":"123456"}'
router.POST("/setValue", Handler::setValue);
router.GET("/getValue", Handler::getValue);
router.POST("/login", Handler::login);
router.POST("/dev", Handler::DeviceManage);
// curl -v http://ip:port/data
router.GET("/data", [](HttpRequest* req, HttpResponse* resp) {
static char data[] = "0123456789";
return resp->Data(data, 10 /*, false */);
});
// curl -v http://ip:port/html/index.html
router.GET("/html/index.html", [](HttpRequest* req, HttpResponse* resp) {
return resp->File("html/index.html");
});
// curl -v http://ip:port/paths
router.GET("/paths", [&router](HttpRequest* req, HttpResponse* resp) {
return resp->Json(router.Paths());
});
// curl -v http://ip:port/get?env=1
router.GET("/get", [](HttpRequest* req, HttpResponse* resp) {
resp->json["origin"] = req->client_addr.ip;
resp->json["url"] = req->url;
resp->json["args"] = req->query_params;
resp->json["headers"] = req->headers;
return 200;
});
// curl -v http://ip:port/service
router.GET("/service", [](const HttpContextPtr& ctx) {
ctx->setContentType("application/json");
ctx->set("base_url", ctx->service->base_url);
ctx->set("document_root", ctx->service->document_root);
ctx->set("home_page", ctx->service->home_page);
ctx->set("error_page", ctx->service->error_page);
ctx->set("index_of", ctx->service->index_of);
return 200;
});
// curl -v http://ip:port/echo -d "hello,world!"
router.POST("/echo", [](const HttpContextPtr& ctx) {
return ctx->send(ctx->body(), ctx->type());
});
// wildcard *
// curl -v http://ip:port/wildcard/any
router.GET("/wildcard*", [](HttpRequest* req, HttpResponse* resp) {
std::string str = req->path + " match /wildcard*";
return resp->String(str);
});
// curl -v http://ip:port/async
router.GET("/async", [](const HttpRequestPtr& req, const HttpResponseWriterPtr& writer) {
writer->Begin();
writer->WriteHeader("X-Response-tid", hv_gettid());
writer->WriteHeader("Content-Type", "text/plain");
writer->WriteBody("This is an async response.\n");
writer->End();
});
// curl -v http://ip:port/www.*
// curl -v http://ip:port/www.example.com
router.GET("/www.*", [](const HttpRequestPtr& req, const HttpResponseWriterPtr& writer) {
HttpRequestPtr req2(new HttpRequest);
req2->url = req->path.substr(1);
requests::async(req2, [writer](const HttpResponsePtr& resp2){
writer->Begin();
if (resp2 == NULL) {
writer->WriteStatus(HTTP_STATUS_NOT_FOUND);
writer->WriteHeader("Content-Type", "text/html");
writer->WriteBody("<center><h1>404 Not Found</h1></center>");
} else {
writer->WriteResponse(resp2.get());
}
writer->End();
});
});
// curl -v http://ip:port/sleep?t=1000
router.GET("/sleep", Handler::sleep);
// curl -v http://ip:port/setTimeout?t=1000
router.GET("/setTimeout", Handler::setTimeout);
// curl -v http://ip:port/query?page_no=1\&page_size=10
router.GET("/query", Handler::query);
// Content-Type: application/x-www-form-urlencoded
// curl -v http://ip:port/kv -H "content-type:application/x-www-form-urlencoded" -d 'user=admin&pswd=123456'
router.POST("/kv", Handler::kv);
// Content-Type: application/json
// curl -v http://ip:port/json -H "Content-Type:application/json" -d '{"user":"admin","pswd":"123456"}'
router.POST("/json", Handler::json);
// Content-Type: multipart/form-data
// bin/curl -v http://ip:port/form -F 'user=admin' -F 'pswd=123456'
router.POST("/form", Handler::form);
// curl -v http://ip:port/test -H "Content-Type:application/x-www-form-urlencoded" -d 'bool=1&int=123&float=3.14&string=hello'
// curl -v http://ip:port/test -H "Content-Type:application/json" -d '{"bool":true,"int":123,"float":3.14,"string":"hello"}'
// bin/curl -v http://ip:port/test -F 'bool=1' -F 'int=123' -F 'float=3.14' -F 'string=hello'
router.POST("/test", Handler::test);
// Content-Type: application/grpc
// bin/curl -v --http2 http://ip:port/grpc -H "content-type:application/grpc" -d 'protobuf'
router.POST("/grpc", Handler::grpc);
// RESTful API: /group/:group_name/user/:user_id
// curl -v -X DELETE http://ip:port/group/test/user/123
router.Delete("/group/:group_name/user/:user_id", Handler::restful);
// router.Delete("/group/{group_name}/user/{user_id}", Handler::restful);
// curl -v http://ip:port/upload?filename=LICENSE -d '@LICENSE'
// curl -v http://ip:port/upload -F 'file=@LICENSE'
router.POST("/upload", Handler::upload);
// curl -v http://ip:port/upload/README.md -d '@README.md'
router.POST("/upload/{filename}", Handler::recvLargeFile);
// SSE: Server Send Events
// @test html/EventSource.html EventSource.onmessage
router.GET("/sse", Handler::sse);
}
实践
/**
* 2022/11/4 与电脑客户端交互
*/
int Handler::setValue(HttpRequest* req, HttpResponse* resp) {
//拿到数据 存入数据库
cout << req->body << endl;
if (req->content_type != APPLICATION_JSON) {
return response_status(resp, HTTP_STATUS_BAD_REQUEST);
}
resp->content_type = APPLICATION_JSON;
hv::Json jsonData = req->GetJson();
string jsonStr = jsonData.dump();
cout << jsonStr << endl;
Json::Value rValue;
Json::Reader reader;
if (!reader.parse(jsonStr.c_str(), rValue)) {
resp->SetBody("0");
return 0;
}
string SOC_IP = rValue["data"]["SOC_IP"].asString();
string SOC_MAC = rValue["data"]["SOC_MAC"].asString();
string NXP_IP = rValue["data"]["NXP_IP"].asString();
string NXP_MAC = rValue["data"]["NXP_MAC"].asString();
string NXP_VERSION = rValue["data"]["NXP_VERSION"].asString();
string HISI_IP = rValue["data"]["HISI_IP"].asString();
string HISI_MAC = rValue["data"]["HISI_MAC"].asString();
string FPGA_VERSION = rValue["data"]["FPGA_VERSION"].asString();
string HISI_VERSION = rValue["data"]["HISI_VERSION"].asString();
string FACTORY_NAME = rValue["data"]["FACTORY_NAME"].asString();
string BARCODE = rValue["data"]["BARCODE"].asString();
string MANUFACTRING_DATE = rValue["data"]["MANUFACTRING_DATE"].asString();
string ASSAMBLY_DATE = rValue["data"]["ASSAMBLY_DATE"].asString();
deviceStruct deviceStruct;
deviceStruct.SOC_IP = SOC_IP;
deviceStruct.SOC_MAC = SOC_MAC;
deviceStruct.NXP_IP = NXP_IP;
deviceStruct.NXP_MAC = NXP_MAC;
deviceStruct.NXP_VERSION = NXP_VERSION;
deviceStruct.HISI_IP = HISI_IP;
deviceStruct.HISI_MAC = HISI_MAC;
deviceStruct.FPGA_VERSION = FPGA_VERSION;
deviceStruct.HISI_VERSION = HISI_VERSION;
deviceStruct.FACTORY_NAME = FACTORY_NAME;
deviceStruct.BARCODE = BARCODE;
deviceStruct.MANUFACTRING_DATE = MANUFACTRING_DATE;
deviceStruct.ASSAMBLY_DATE = ASSAMBLY_DATE;
if (mySqlObj.InsertData(deviceStruct, "deviceTable")) {
resp->SetBody("1");
}
else
{
resp->SetBody("0");
}
return 200;
}
/**
* 2022/11/4 与APP交互 与电脑端查询接口交互
*/
int Handler::getValue(HttpRequest* req, HttpResponse* resp) {
//取出传入的code值 遍历数据库找到返回json 未找到返回未找到
std::map<std::string, std::string>::const_iterator it = req->query_params.begin();
req->query_params.size();
for (; it != req->query_params.end(); it++)
{
cout << "key=" << it->first << " value=" << it->second << endl;
//查询到
deviceStruct devStruct = {""};
if (mySqlObj.QueryDatabase1(it->second, devStruct))
{
//组成json 发出去
Json::Value rValue;
rValue["SOC_IP"] = Json::Value(devStruct.SOC_IP);
rValue["SOC_MAC"] = Json::Value(devStruct.SOC_MAC);
rValue["NXP_IP"] = Json::Value(devStruct.NXP_IP);
rValue["NXP_MAC"] = Json::Value(devStruct.NXP_MAC);
rValue["NXP_VERSION"] = Json::Value(devStruct.NXP_VERSION);
rValue["HISI_IP"] = Json::Value(devStruct.HISI_IP);
rValue["HISI_MAC"] = Json::Value(devStruct.HISI_MAC);
rValue["FPGA_VERSION"] = Json::Value(devStruct.FPGA_VERSION);
rValue["HISI_VERSION"] = Json::Value(devStruct.HISI_VERSION);
rValue["FACTORY_NAME"] = Json::Value(devStruct.FACTORY_NAME);
rValue["BARCODE"] = Json::Value(devStruct.BARCODE);
rValue["MANUFACTRING_DATE"] = Json::Value(devStruct.MANUFACTRING_DATE);
rValue["ASSAMBLY_DATE"] = Json::Value(devStruct.ASSAMBLY_DATE);
string str = Json::FastWriter().write(rValue);
resp->SetBody(str);
cout << str << endl;
}
else {
//查询不到
resp->SetBody("0");
}
}
return 632222222;
}
数据库操作:
#include <stdio.h>
#include <WinSock.h> //一定要包含这个
#include "define.h"
#include <Windows.h>
#include "mysqlSelf.h"
//包含附加依赖项,也可以在工程--属性里面设置
#pragma comment(lib,"wsock32.lib")
#pragma comment(lib,"libmysql.lib")
CMySqlSelf::CMySqlSelf()
{
init();
}
CMySqlSelf::~CMySqlSelf()
{
FreeConnect();
}
void CMySqlSelf::init()
{
ConnectDatabase();
CreateTable();
return;
}
/**
* 创建表
*/
bool CMySqlSelf::CreateTable()
{
int ret = 0;
string strSql = "CREATE TABLE if not exists deviceTable(ID INT auto_increment primary key,SOC_IP VARCHAR(255), SOC_MAC VARCHAR(255), NXP_IP VARCHAR(255), NXP_MAC VARCHAR(255), NXP_VERSION VARCHAR(255), HISI_IP VARCHAR(255), HISI_MAC VARCHAR(255), FPGA_VERSION VARCHAR(255), HISI_VERSION VARCHAR(255),FACTORY_NAME VARCHAR(255),BARCODE VARCHAR(255),MANUFACTRING_DATE VARCHAR(255),ASSAMBLY_DATE VARCHAR(255));";
if (mysql_query(&mysql, strSql.c_str())) {
printf("Create failed (%s)", mysql_error(&mysql));
return false;
}
else
{
printf("Create sucess");
}
}
/**
* 连接数据库
*/
bool CMySqlSelf::ConnectDatabase() {
//初始化mysql
mysql_init(&mysql);
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "utf8");
mysql_options(&mysql, MYSQL_INIT_COMMAND, "SET NAMES utf8");
const char host[] = "127.0.0.1";
const char user[] = "root";
const char psw[] = "123456";
const char table[] = "scantools";
const int port = 3306;
//返回false则连接失败,返回true则连接成功
if (!(mysql_real_connect(&mysql, host, user, psw, table, port, NULL, 0)))
//中间分别是主机,用户名,密码,数据库名,端口号(可以写默认0或者3306等),可以先写成参数再传进去
{
printf("Error connecting to database:%s", mysql_error(&mysql));
return false;
}
else
{
printf("connect");
return true;
}
}
/**
* 释放资源
*/
void CMySqlSelf::FreeConnect() {
mysql_free_result(res); //释放一个结果集合使用的内存。
mysql_close(&mysql); //关闭一个服务器连接。
}
/*
* 转码
*/
string BitStrToStr(string bstr) {
string str = "";
//每八位转化成十进制,然后将数字结果转化成字符
int sum;
for (int i = 0; i < bstr.size(); i += 8)
{
sum = 0;
for (int j = 0; j < 8; j++)
if (bstr[i + j] == '1')
sum = sum * 2 + 1;
else
sum = sum * 2;
str = str + char(sum);
}
return str;
}
/**
* 插入
*/
bool CMySqlSelf::InsertData(deviceStruct info,string tableName) {
char strSql[1024 * 1024] = { 0 };
sprintf(strSql,
"INSERT INTO devicetable(SOC_IP,SOC_MAC,NXP_IP,NXP_MAC,NXP_VERSION,HISI_IP,HISI_MAC,FPGA_VERSION,HISI_VERSION,FACTORY_NAME,BARCODE,MANUFACTRING_DATE,ASSAMBLY_DATE)VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')",
info.SOC_IP.c_str(),
info.SOC_MAC.c_str(),
info.NXP_IP.c_str(),
info.NXP_MAC.c_str(),
info.NXP_VERSION.c_str(),
info.HISI_IP.c_str(),
info.HISI_MAC.c_str(),
info.FPGA_VERSION.c_str(),
info.HISI_VERSION.c_str(),
info.FACTORY_NAME.c_str(),
info.BARCODE.c_str(),
info.MANUFACTRING_DATE.c_str(),
info.ASSAMBLY_DATE.c_str());
printf(strSql);
if (mysql_query(&mysql, strSql))
{
printf("m_query failed (%s)", mysql_error(&mysql));
return false;
}
else
{
printf("Insert success");
return true;
}
}
/**
* 查询
*/
string dbValue(MYSQL_ROW col, int index)
{
if (col[index])
{
return col[index];
}
return "";
}
bool CMySqlSelf::QueryDatabase1(string s, deviceStruct& devStruct) {
memset(m_query, 0, 150);
s = "select * from deviceTable where BARCODE = " + s;
//s = "select * from deviceTable";
memcpy(m_query, s.c_str(), sizeof(s));//写insert语句
if (mysql_query(&mysql, m_query)){
printf("Query failed (%s)", mysql_error(&mysql));
return false;
}
else
{
printf("Query success");
}
//获取结果集
res = mysql_store_result(&mysql);
if (!res) //获得sql语句结束后返回的结果集
{
printf("Couldn't get result from %s", mysql_error(&mysql));
return false;
}
int index = 1;
while (column = mysql_fetch_row(res)) //在已知字段数量情况下,获取并打印下一行
{
devStruct.SOC_IP = dbValue(column, index++);
devStruct.SOC_MAC = dbValue(column, index++);
devStruct.NXP_IP = dbValue(column, index++);
devStruct.NXP_MAC = dbValue(column, index++);
devStruct.NXP_VERSION = dbValue(column, index++);
devStruct.HISI_IP = dbValue(column, index++);
devStruct.HISI_MAC = dbValue(column, index++);
devStruct.FPGA_VERSION = dbValue(column, index++);
devStruct.HISI_VERSION = dbValue(column, index++);
devStruct.FACTORY_NAME = dbValue(column, index++);
devStruct.BARCODE = dbValue(column, index++);
devStruct.MANUFACTRING_DATE = dbValue(column, index++);
devStruct.ASSAMBLY_DATE = dbValue(column, index++);
// printf("%10s %10s %10s %10s", column[0], column[1], column[2], column[3]); //column是列数组
}
return true;
}
数据字段定义了一个结构体:
//结构体
struct deviceStruct
{
string SOC_IP;
string SOC_MAC;
string NXP_IP;
string NXP_MAC;
string NXP_VERSION;
string HISI_IP;
string HISI_MAC;
string FPGA_VERSION;
string HISI_VERSION;
string FACTORY_NAME;
string BARCODE;
string MANUFACTRING_DATE;
string ASSAMBLY_DATE;
}
mysql可视化工具用的是navicat,数据库里的信息如下: