当前位置: 首页 > java >正文

Qt笔记整理(1)

一. 客户端和服务器连接的步骤

1.项目配置

.pro文件夹network模块QT += core gui network sql

QT       += core gui network sql

2.定义网络对象

Client函数中,定义QTcpSocket对象类型的成员变量m_socket 

class Client : public QWidget
{//...
public:// 
public slots://
private:QTcpSocket m_socket;//QTcpSocket 是 Qt 中用于 TCP 通信的核心类,定义为成员变量后,可在类的各个函数中操作 socket(连接、发送 / 接收数据等 )
};

3.连接

在client构造函数中,通过m_socket调用 m_socket.connectToHost(ip, port)发起连接到服务器,参数为ip和port成员变量(ip需要强转成QHostAddress)

4.结果打印

定义槽函数showConnect,打印连接服务器成功

5.关联信号与槽

在构造函数connect 绑定 connected 信号


Client::Client(QWidget *parent): QWidget(parent), ui(new Ui::Client)
{ui->setupUi(this);loadConfig();m_socket.connectToHost(QHostAddress(m_strIP),m_usPort);
// 信号槽关联:m_socket 发出 connected 信号时,调用当前类的 showConnect 槽函数
//1.谁发的信号2.发的什么信号3.谁处理的信号4.槽函数connect(&m_socket,&QTcpSocket::connected,this,&Client::showConnect);}void Client::showConnect()
{qDebug()<<"连接服务器成功";
}

客户端连接服务器完整流程:

1.项目配置加 network 模块 → 2. 定义 QTcpSocket 成员变量 → 3. 构造函数中调用 connectToHost(ip, port) 发起连接 → 4. 定义槽函数 showConnect 处理连接成功 → 5. 用 connect 关联 QTcpSocket::connected 信号与槽函数。

2. 创建一个单例模式的步骤

单例模式核心目标是保证一个类只有一个实例,并提供全局访问点。

1.私有化构造相关函数

私有化构造函数:防止外部直接 new Client 创建对象。
私有化拷贝构造函数和赋值运算符:防止通过拷贝或赋值创建新对象。

class Client : public QWidget
{
public://
public slots://
private://// 私有化构造函数:外部无法直接 new ClientClient(QWidget *parent = nullptr);// 私有化拷贝构造函数:禁止拷贝对象Client(const Client& instance)=delete;// 私有化赋值运算符:禁止对象赋值Client& operator=(const Client&)=delete;
};

2. 定义静态获取

定义获取单例的静态函数,创建静态局部对象,并返回其引用

class Client : public QWidget
{public:static Client& getInstance();
//Client &Client::getInstance()
{static Client instance;return instance;
}

3.通过静态函数创建  获取

main.cpp中创建的Client对象改为使用全局访问节点创建

    Client::getInstance().show();

3. 创建一个pdu并给每个成员变量赋值的步骤

1.定义pdu结构体 

struct PDU {//协议数据单元unsigned int uiPDULen;   // 协议总长度 = 结构体固定部分 + 柔性数组长度  unsigned int uiMsgLen;   // 实际消息(柔性数组)的有效长度  unsigned int uiMsgType;  // 消息类型(枚举区分,如注册请求/响应)  char caData[64];         // 固定参数(长度固定)  char caMsg[];            // 柔性数组(存实际消息,长度动态)  
};

2.定义消息类型的枚举值

num ENUM_MSG_TYPE{//消息类型的枚举值ENUM_MSG_TYPE_MIN=0,ENUM_MSG_TYPE_REGIST_REQUEST,ENUM_MSG_TYPE_REGIST_RESPOND,ENUM_MSG_TYPE_MAX=0x00ffffff
};

3.定义沟通pdu函数,参数是消息长度

1.计算协议总长度 uiPDULen

2.根据长度申请空间,结果判空是否申请失败

3.初始化内存(memset赋 0)

4. pdu的两个长度赋值
记录实际消息长度(柔性数组有效长度)  
记录协议总长度(固定部分 + 柔性数组)  

PDU *mkPDU(uint uiMsgType,uint uiMsgLen)
{uint uiPDULen=uiMsgLen+sizeof(PDU);//实际消息长度+pdu结构体长度PDU* pdu = (PDU*)malloc(uiPDULen);//动态分配内存,申请 uiPDULen 大小的内存,强制转换为 PDU* 类型,让 pdu 指向可容纳结构体固定部分 + 柔性数组的内存块。if (pdu == NULL) {exit(1);}memset(pdu, 0, uiPDULen);pdu->uiMsgLen=uiMsgLen;pdu->uiPDULen=uiPDULen;pdu->uiMsgType=uiMsgType;return pdu;}


4. memcpy函数的每个参数的含义和怎么传

memcpy函数原型

void* memcpy(void* destination, const void* source, size_t num);

目标地址 源地址 

 memcpy(pdu->caMsg, strMsg.toStdString().c_str(), strMsg.toStdString().size());

往pdu中存东西怎么传

void Client::on_send_PB_clicked()
{QString strMsg = ui->input_LE->text();if (strMsg.isEmpty()) {return;}PDU* pdu = mkPDU(strMsg.toStdString().size() + 1);pdu->uiMsgType = ENUM_MSG_TYPE_REGIST_REQUEST;memcpy(pdu->caMsg, strMsg.toStdString().c_str(), strMsg.toStdString().size());m_socket.write((char*)pdu, pdu->uiPDULen);qDebug() << "send msg uiPDULen" << pdu->uiPDULen<< "uiMsgLen" << pdu->uiMsgLen<< "uiMsgType" << pdu->uiMsgType<< "caData" << pdu->caData<< "caMsg" << pdu->caMsg;free(pdu);pdu = NULL;
}

5. conncet函数每个参数的函数和怎么传

QMetaObject::Connection connect(const QObject *sender,      // 发送信号的对象PointerToMemberFunction signal, // 信号的成员函数指针const QObject *receiver,    // 接收信号的对象PointerToMemberFunction method, // 槽函数的成员函数指针Qt::ConnectionType type = Qt::AutoConnection // 连接类型,可选
);

connect(this, &QTcpSocket::readyRead, this, &MyTcpSocket::recvMsg);

发送信号的对象  信号成员函数指针 接收信号对象   槽函数的成员函数指针


从pdu 中取东西怎么传

MyTcpSocket::MyTcpSocket()
{// 关联接收到消息的信号和处理接收的函数connect(this, &QTcpSocket::readyRead, this, &MyTcpSocket::recvMsg);
}void MyTcpSocket::recvMsg()
{qDebug() << "recvMsg 接收消息长度: " << this->bytesAvailable();unsigned int uiPDULen = 0;this->read((char*)&uiPDULen, sizeof(unsigned int));PDU* pdu = mkPDU(uiPDULen - sizeof(PDU));this->read((char*)(pdu + sizeof(unsigned int)), uiPDULen - sizeof(unsigned int));qDebug() << "recvMsg uiPDULen" << uiPDULen<< "uiMsgLen" << pdu->uiMsgLen<< "uiMsgType" << pdu->uiMsgType<< "caData" << pdu->caData<< "caMsg" << pdu->caMsg;free(pdu);pdu = NULL;
}
http://www.xdnf.cn/news/15708.html

相关文章:

  • CCF编程能力等级认证GESP—C++5级—20250628
  • 使用nvm安装node、npm、pnpm以及编译项目教程
  • SpringBoot 3.0 挥别 spring.factories,拥抱云原生新纪元
  • 基于大模型打造故障预警服务器巡检机器人
  • Jetpack Compose中的Modifier:UI元素的装饰与行为扩展
  • 3-大语言模型—理论基础:生成式预训练语言模型GPT(代码“活起来”)
  • [论文阅读] 软件工程 | 用模糊逻辑“解锁”项目成功:告别非黑即白的评估时代
  • 网络基础DAY13-NAT技术
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 基于wordcloud库实现词云图
  • OSPF高级特性之Overflow
  • 浅谈Rust语言特性
  • 1 渗透基础
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - snowNLP库实现中文情感分析
  • 【unitrix】 6.7 基本结构体(types.rs)
  • Python 使用期物处理并发(使用concurrent.futures模块下载)
  • Leetcode刷题营第三十三题:对称二叉树
  • 五大开源OCR开源框架评估01-Tesseract:OCR 领域的远古巨神
  • Docker安装教程
  • GaussDB join 连接的用法
  • 7.18 Java基础 |
  • 正则表达式,Collection集合,迭代器
  • 差分数组算法
  • [simdjson] 填充字符串 | `document` 对象 | on-demand 模式
  • C++并发编程-14. 利用栅栏实现同步
  • Redis学习其三(订阅发布,主从复制,哨兵模式)
  • Windows 安装WSL +Docker 部署通义千问大模型(同步解决Ubuntu启动命令闪退)
  • 图片平铺下去总是有个缝隙的解决方案
  • Vue常见指令
  • 【解码文本世界的“隐形分界线”:Windows与Linux回车换行之谜】
  • Python网络爬虫之selenium库