VS2022配合Qt与boost.asio实现一个TCP异步通信系统远程操作mysql数据库

news2024/11/15 13:58:37

        上一篇博客我们通过boost.asio搭建了一个简单的异步服务器,但是那是基于命令行的,所有用起来还是相当枯燥的,这次我们配合Qt实现一个简陋的前端页面来控制后端mysql数据库中的表,实现添加密钥的功能(本次博客使用的boost版本是1.84.0,mysql版本是8,Qt版本是6,并且本次博客主要展示代码和效果,不做代码讲解,因为本次博客所使用的代码都是之前博客中所使用过的,大家可以去我的主页学习)。

服务器端

main.cpp

#include <QtWidgets/QApplication>
#include<QtSql/QSqlDatabase>
#include<QtSql/QSqlError>
#include<QtSql/QSqlQuery>
#include<random>
#include<iostream>
#include"Server.h"
int main(int argc, char *argv[])
{
	QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
	try
	{
		db.setPort(3306);
		db.setHostName("localhost");
		db.setDatabaseName("booksystem");
		db.setUserName("root");
		db.setPassword("2145");
		if (!db.open())
		{
			throw QSqlError("连接失败:", db.lastError().text());
		}
	}
	catch (const QSqlError &e)
	{
		qDebug() << "数据库连接出错了:" << e.text();
	}
	boost::asio::io_context ioContext;
	Server s(ioContext, 10240);
	ioContext.run();
	return 0;
}

Server.h

#pragma once
#include"Session.h"
class Server
{
public:
	Server(boost::asio::io_context& ioc, int port);
	void start_accept();
	void handle_accept(Session* s,const boost::system::error_code& e);
private:
	boost::asio::io_context &ioc;
	boost::asio::ip::tcp::acceptor act;
};

Server.cpp

#include"Server.h"
Server::Server(boost::asio::io_context& ioc, int port) :ioc(ioc), act(ioc,boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4::any(), port))
{
	start_accept();
}
void Server::start_accept()
{
	Session* s = new Session(ioc);
	act.async_accept(s->get_socket(), std::bind(&Server::handle_accept, this, s, std::placeholders::_1));
}
void Server::handle_accept(Session* s, const boost::system::error_code& e)
{
	if (!e)
	{
		s->Start();
	}
	else
	{
		delete s;
	}
	start_accept();
}

Session.h 

#pragma once
#include<boost/asio.hpp>
class Session
{
public:
	Session(boost::asio::io_context& ioc);
	void Start();
	void handle_recive(const::boost::system::error_code &e, int recived_len);
	void handle_send(const::boost::system:: error_code &e);
	boost::asio::ip::tcp::socket &get_socket();
private:
	boost::asio::ip::tcp::socket soc;
	char data[1024];
	int max_len = 1024;
};

Session.cpp

#include"Session.h"
#include<iostream>
#include<QtSql/QSqlQuery>
#include<QtSql/QSqlError>
Session::Session(boost::asio::io_context& ioc) :soc(ioc)
{
}
boost::asio::ip::tcp::socket & Session::get_socket()
{
	return this->soc;
}
void Session::Start()
{
	memset(data, '\0', max_len);
	soc.async_receive(boost::asio::buffer(data, max_len), std::bind(&Session::handle_recive, this, std::placeholders::_1, std::placeholders::_2));
}
void Session::handle_recive(const::boost::system::error_code& e, int recived_len)
{
	if (!e)
	{
		std::cout << "recived:" << data<<std::endl;
		QSqlQuery q;
		QString sql = "insert into booksystem.secret (secrets)values(?)";
		q.prepare(sql);
		q.addBindValue(QString(data));
		if (!q.exec())
		{
			std::cout << "添加失败" << q.lastError().text().toStdString() << std::endl;
		}
		q.clear();//这个必须要放在async_send函数的前面,不然handle_recive函数结束的时候就会出错
		soc.async_send(boost::asio::buffer(data,max_len), std::bind(&Session::handle_send, this, std::placeholders::_1));
	}
	else
	{
		delete this;
	}
}
void Session::handle_send(const::boost::system::error_code& e)
{
	if (!e)
	{
		memset(data, '\0', max_len);
		soc.async_receive(boost::asio::buffer(data, max_len), std::bind(&Session::handle_recive, this, std::placeholders::_1, std::placeholders::_2));
	}
	else
	{
		delete this;
	}
}

客户端

由于我们是使用VS2022作为开发平台所有并没有使用Qt Creator会使用的qmake,因此也没有对应的.pro文件,这样的好处就是,我们不必在.pro文件中配置项目的文件和第三方库了。

main.cpp

#include "QtClient.h"
#include <QtWidgets/QApplication>
#include<boost/asio.hpp>
#include<iostream>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
	boost::asio::io_context ioContext;
	QtClient w(a.activeWindow(), &ioContext);
	try
	{
		// 创建socket对象并连接到服务器
		boost::asio::ip::tcp::socket socket(ioContext);
		boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string("127.0.0.1"), 10240);
		socket.connect(endpoint);
	}
	catch (boost::system::system_error& e)
	{
		std::cout<< "Exception: " << e.what() << std::endl;
	}
	w.show();
    return a.exec();
}

QtClient.h

#pragma once

#include <QtWidgets/QWidget>
#include "ui_QtClient.h"
#include<boost/asio.hpp>
class QtClient : public QWidget
{
    Q_OBJECT

public:
    QtClient(QWidget *parent = nullptr,boost::asio::io_context *ioc=nullptr);
    ~QtClient();
private slots:
    void add_button_click();
private:
    Ui::QtClientClass ui;
    boost::asio::ip::tcp::socket soc;
};

QtClient.cpp 

#include "QtClient.h"
#include<iostream>
QtClient::QtClient(QWidget *parent,boost::asio::io_context *ioc):soc(*ioc),QWidget(parent)
{
    ui.setupUi(this);
    ui.secretText->setAlignment(Qt::AlignCenter);
    soc.connect(boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string("127.0.0.1"), 10240));
    connect(ui.addButton, &QPushButton::clicked, this, &QtClient::add_button_click);
}

QtClient::~QtClient()
{}
void QtClient::add_button_click()
{
    std::cout << "secret get: " << ui.secretText->text().toUtf8().toStdString()<< std::endl;
    QByteArray d = ui.secretText->text().toUtf8();
    char data[1024] = "";
    qstrcpy(data, d.data());
    soc.send(boost::asio::buffer(data));
    char rec[1024] = "";
    soc.receive(boost::asio::buffer(rec, 1024));
    std::cout << "reply:" << rec << std::endl;
}

ui_QtClient.h

/********************************************************************************
** Form generated from reading UI file 'QtClient.ui'
**
** Created by: Qt User Interface Compiler version 6.6.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/

#ifndef UI_QTCLIENT_H
#define UI_QTCLIENT_H

#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QWidget>

QT_BEGIN_NAMESPACE

class Ui_QtClientClass
{
public:
    QPushButton *addButton;
    QLineEdit *secretText;

    void setupUi(QWidget *QtClientClass)
    {
        if (QtClientClass->objectName().isEmpty())
            QtClientClass->setObjectName("QtClientClass");
        QtClientClass->resize(600, 400);
        QtClientClass->setStyleSheet(QString::fromUtf8("background-color: rgb(255, 170, 255);"));
        addButton = new QPushButton(QtClientClass);
        addButton->setObjectName("addButton");
        addButton->setGeometry(QRect(220, 220, 151, 51));
        addButton->setStyleSheet(QString::fromUtf8("background-color: rgb(85, 255, 255);\n"
"font: 12pt \"Microsoft YaHei UI\";\n"
"border: 3 solid rgb(0, 0, 255);"));
        secretText = new QLineEdit(QtClientClass);
        secretText->setObjectName("secretText");
        secretText->setGeometry(QRect(80, 110, 441, 71));
        secretText->setStyleSheet(QString::fromUtf8("font: 16pt \"Microsoft YaHei UI\";\n"
"background-color: rgb(0, 255, 127);\n"
"border:3 solid rgb(0, 170, 0);"));

        retranslateUi(QtClientClass);

        QMetaObject::connectSlotsByName(QtClientClass);
    } // setupUi

    void retranslateUi(QWidget *QtClientClass)
    {
        QtClientClass->setWindowTitle(QCoreApplication::translate("QtClientClass", "QtClient", nullptr));
        addButton->setText(QCoreApplication::translate("QtClientClass", "\346\267\273\345\212\240\345\257\206\351\222\245", nullptr));
        secretText->setPlaceholderText(QCoreApplication::translate("QtClientClass", "\350\257\267\350\276\223\345\205\245\345\257\206\351\222\245", nullptr));
    } // retranslateUi

};

namespace Ui {
    class QtClientClass: public Ui_QtClientClass {};
} // namespace Ui

QT_END_NAMESPACE

#endif // UI_QTCLIENT_H

运行效果

显然左边的窗口是服务器窗口,右边两个窗口是客户端的界面窗口和控制台窗口,有的人因为项目属性配置的问题,可能只有界面窗口,不过没什么影响啦。

输入我们要添加的密钥后,点击添加按钮,发现服务器成功添加了密钥,并且向客户端发送了响应,并且客户端也接收到了响应。

 打开mysql里面的secret表,发现我们的密钥添加进去了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1701748.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为什么大部分新手做抖音小店赚不到钱?

大家好&#xff0c;我是喷火龙。 今天来给大家聊聊&#xff0c;为什么大部分新手做抖店赚不到钱&#xff1f; 不知道大家想过这个问题没有&#xff0c;可能有些人把赚不到钱的原因归结于市场、或者平台、又或者运营技术以及做店经验。 但我觉得这些都不是重点&#xff0c;重…

关于RAG(检索增强生成)的一些知识

写在前面 最近一直在看AI相关的文章&#xff0c;不出意外的话&#xff0c;后续几篇应该都是关于这方面的。希望能和大家一起了解这方面的技术。 什么是RAG 检索增强生成 (RAG,全称Retrieval-Augmented Generation) 是一种利用从外部来源获取的事实来提高生成式 AI 模型的准确…

视频监控管理平台LntonCVS安防监控平台实现接入监控视频资源的视频汇聚方案

随着各行业数字化转型的不断推进&#xff0c;视频监控技术在行业内的安防应用及管理支撑日益增多。然而&#xff0c;由于前期规划不清晰、管理不到位等问题&#xff0c;视频监管系统普遍存在以下问题&#xff1a; 1. 各部门单位在视频平台建设中以所属领域为单位&#xff0c;导…

Intellij IDEA创建springboot 3.2.5 项目

1、idea file -> new ->Project 点击 2、创建项目配置 完成配置-> 点击Next 3、选择对应jar 包 -> 点击Create 4、删除 .mvn、mvnw、mvnw.cmd

宝塔Nginx设置图片访问跨域

宝塔Nginx设置图片访问跨域 针对某一个站点设置 找到对应的站点点击 “设置” 增加对应header设置 代码&#xff1a; location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)${#允许跨域add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Headers X-Requeste…

数字图像处理系列 | 非线性滤波 (4)

非线性滤波就不能做卷积了 文章目录 前言. 去除噪声如果使用线性滤波 1. 中值滤波2. 重新思考一下 -- 高斯平滑滤波高斯平滑哪里不好用呢&#xff1f;but&#xff0c;我们是不是可以结合高斯平滑滤波的优点和非线性滤波的优点&#xff0c;来做这个去噪呢&#xff1f; 3. Bilat…

融资融券保证金比例,融资融券最低利率4.0%

融资融券保证金比例是指投资者交付的保证金与融资、融券交易金额的比例&#xff0c;用于控制投资者初始资金的放大倍数。这个比例分为融资保证金比例和融券保证金比例。 融资融券保证金比例的计算 1. 融资保证金比例是指投资者融资买入证券时交付的保证金与融资交易金额的比例…

Rust之函数式语言特性:迭代器和闭包(一):概述

开发环境 Windows 11Rust 1.78.0 VS Code 1.89.1 项目工程 这次创建了新的工程minigrep. 函数式语言特性:迭代器和闭包 Rust的设计从许多现有语言和技术中获得了灵感&#xff0c;其中一个重要影响是函数式编程。函数式编程通常包括通过在参数中传递函数、从其他函数返回函数、…

线程池(详细)

Java中的线程池是运用场景最多的并发框架&#xff0c;几乎所有需要异步或并发执行任务的程序都可以使用线程池。在开发过程中&#xff0c;合理地使用线程池能够带来3个好处。 第一&#xff1a;降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 第二&…

2024年电工杯数学建模竞赛思路资料汇总贴

下文包含&#xff1a;2024电工杯&#xff08;电工杯数学建模竞赛&#xff09;思路解析、电工杯参赛时间及规则信息说明、好用的数模技巧及如何备战数学建模竞赛 C君将会第一时间发布选题建议、所有题目的思路解析、相关代码、参考文献、参考论文等多项资料&#xff0c;帮助大家…

前端怎么使用svg格式的图片

目录 第一步&#xff0c;找到图标 第二步&#xff0c;使用 第一种&#xff0c;SVG下载 第二种&#xff0c;粘贴SVG代码 第一步&#xff0c;找到图标 以阿里巴巴矢量图标库为例&#xff0c;随便找一个图标&#xff0c;如下图 第二步&#xff0c;使用 第一种&#xff0c;SV…

Matlab 2023b学习笔记1——界面认识

下载安装好Matlab后&#xff0c;可以看到如下界面&#xff1a; 可以看到&#xff0c;这时只有命令行窗口。我们在上方工具栏中选择“布局”—— “默认”&#xff0c;即可看到左右两边多出来了“当前文件夹”与“工作区”两栏。 一、当前文件夹界面 这个界面显示的是当前目录下…

什么是独特摆动交易策略?fpmarkets1分钟讲清楚

摆动交易策略想必各位投资者都已经接触过了&#xff0c;但是什么是独特摆动交易策略&#xff1f;各位投资者知道吗&#xff1f;其实很简单&#xff0c;这是一种基于斐波纳契工具的独特摆动交易策略。下面fpmarkets1分钟讲清楚&#xff0c;趋势总会经历调整&#xff0c;而这些调…

一个Python浏览器自动化操作神器:Mechanize库

今天&#xff0c;我们将介绍一个强大的Python库——Mechanize&#xff0c;通过它&#xff0c;我们可以轻松实现网页浏览的自动化。 Mechanize是一个用于模拟浏览器行为的Python库。它允许你自动化地与网站进行交互&#xff0c;就像真实用户一样。你可以使用它填写表单、点击按…

Python考试复习--day3

1.统计字符串个数 ninput() z0 s0 k0 o0 for i in n:if i.isalpha():zz1elif i.isnumeric():ss1elif i.isspace():k1else:o1 print(字母有{}个,数字有{}个,空格有{}个,其他字符{}个.format(z,s,k,o))2.分类统计字符 ninput() x0 d0 s0 k0 o0 for i in n:if i.islower():x1elif …

ENVI5.6详细安装教程,亲测可用(附安装包和破解文件)

文件准备 下载链接如下&#xff0c;包括安装包envi5.6.exe和破解需要的文件Crack 链接&#xff1a;https://pan.baidu.com/s/1fLE6VcEOqWpN7h0j99evSw?pwd77zx 提取码&#xff1a;77zx --来自百度网盘超级会员V4的分享开始安装 选择下载好的文件进行解压&#xff0c;鼠标…

17 - grace数据处理 - 补充 - 地下水储量计算过程分解 -- 陆地水储量变化

17 - grace数据处理 - 补充 - 地下水储量计算过程分解 -- 陆地水储量变化 0 引言1 Grace陆地水储量过程整合0 引言 最近关于GRACE地下水储量计算的有关过程多被问起,接下来几篇将介绍关于地下水储量计算的有关内容。由水量平衡方程可以将地下水储量的计算过程分解为4个部分,第…

数据集003:猫类识别-12种猫分类数据集 (含数据集下载链接)

数据集简介&#xff1a; 训练集共有2160张猫的图片, 分为12类. train_list.txt是其标注文件 测试集共有240张猫的图片. 不含标注信息. 训练集图像&#xff08;部分&#xff09; 验证集图像&#xff08;部分&#xff09; 标签 部分代码&#xff1a; # 定义训练数据集 class T…

Devexpress中GridControl控件中的表格遍历逻辑问题

当我们在执行其他事件时&#xff0c;常常需要对GridControl控件里的表内容进行一个遍历逻辑判断&#xff0c;该文以确认2列中的值是否为空为例&#xff1b;首先在遍历模块当然是使用foreach作为遍历的基础&#xff0c;在这其中在此例中存在具体业务细节&#xff0c;需要对选中行…

设置 border 边框单侧样式 - HarmonyOSNext

设置 border 边框单侧样式,通过 api 中查看 border(value: BorderOptions): T; BorderOptions 又包含了若干个子属性 1.width?: EdgeWidths | Length; 2.color?: EdgeColors | ResourceColor; 3.radius?: BorderRadiuses | Length; 4.style?: EdgeStyles | BorderStyle; 其…