QT TCP多线程网络通信

学习目标: TCP网络通信编程

学习前置环境

运行环境:qt creator 4.12

QT TCP网络通信编程-CSDN博客

Qt 线程 QThread类详解-CSDN博客

学习内容

使用多线程技术实现服务端计数器

 核心代码

客户端

客户端:负责连接服务端,每次连接次数+1。以及连接的报错信息

#include "dialog.h"
#include "ui_dialog.h"
#include<QDebug>
Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog)
{ui->setupUi(this);ui->server_ip->setText("127.0.0.1");ui->server_port->setText("8888");clientSocket =new QTcpSocket;setWindowTitle("连接计数器客户端");//连接错误回调QObject::connect(clientSocket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, [this](QAbstractSocket::SocketError error){switch (error) {case QAbstractSocket::RemoteHostClosedError: // 远程主机关闭连接// QMessageBox::information(this, "提示", "远程主机关闭连接", QMessageBox::Yes);break;case QAbstractSocket::HostNotFoundError: // 找不到主机地址QMessageBox::information(this, "提示", "找不到主机地址", QMessageBox::Yes);break;case QAbstractSocket::ConnectionRefusedError: // 连接被对方拒绝(或者超时)QMessageBox::information(this, "提示", "连接被对方拒绝(或者超时)", QMessageBox::Yes);break;default:QMessageBox::information(this, "提示", tr("致命错误为:").arg(clientSocket->errorString()), QMessageBox::Yes);}ui->request->setEnabled(true);ui->close->setEnabled(true);});//当 socket 成功连接到服务器时,会发射 connected() 信号。connect(clientSocket,&QTcpSocket::connected,this,[this](){QString str ="已经连接到服务器端\n服务器端ip:"+clientSocket->peerAddress().toString()+"服务器端port:"+QString::number(clientSocket->peerPort());//QMessageBox::information(this, "提示",str , QMessageBox::Yes);ui->request->setEnabled(false);ui->close->setEnabled(true);QString msg=ui->currentv->text()+'\n';clientSocket->write(msg.toUtf8(),msg.length());int count =(ui->currentv->text().toUInt());ui->currentv->setNum(++count);});//当 socket 与服务器断开连接时,会发射 disconnected() 信号。connect(clientSocket,&QTcpSocket::disconnected,this,[this](){QString str ="已断开与服务器端的连接\n服务器端ip:"+clientSocket->peerAddress().toString()+"服务器端port:"+QString::number(clientSocket->peerPort());//QMessageBox::information(this, "提示",str , QMessageBox::Yes);clientSocket->close();});ui->request->setEnabled(true);ui->close->setEnabled(true);}Dialog::~Dialog()
{delete ui;
}void Dialog::on_request_clicked()
{clientSocket->connectToHost(ui->server_ip->text(),ui->server_port->text().toInt());}void Dialog::on_close_clicked()
{clientSocket->close(); // 取消已有的连接  后续触发断开回调ui->request->setEnabled(true);ui->close->setEnabled(false);
}

服务端

新连接请求类

通过继承重写的方式,实现新连接的回调操作。当然你也可以使用信号槽机制。如

connect(tcpServer, &QTcpServer::newConnection,对象,行为)。

实现功能:交给线程池处理,绑定实现连接断开前,把公用计数器+1操作,释放并清理资源。可以理解为绑定亡语操作,死后(连接断开)触发。

#ifndef TCPNEWCONNET_H
#define TCPNEWCONNET_H#include"writethread.h"
#include"dialog.h"class Dialog;class TcpNewConnet : public QTcpServer  //基于重写虚函数 实现新连接回调函数
{
Q_OBJECT
public:TcpNewConnet()=default;~TcpNewConnet()=default;TcpNewConnet(QObject *parent=0):QTcpServer(parent){dlgs =(Dialog*)parent;}
protected:// 当有新连接的时候会自动调用此函数void TcpNewConnet::incomingConnection(qintptr socketdescriptor){WriteThread *thread=new WriteThread(socketdescriptor,0);// 此处用于处理对话框显示统计访问次数信息connect(thread,&QThread::finished,dlgs,&Dialog::slotsdispFunc);connect(thread,&QThread::finished,thread,&QThread::deleteLater);thread->start(); // 通过执行这条语句来调用run()函数
}Dialog *dlgs;
};#endif // TCPNEWCONNET_H

多线程类

依然是通过重写的方式,注意点是Tcpsocket的生命周期,当过了{}作用域会自动释放这条连接。实现了客户端连接成功,再释放。

功能:创造一个连接,然后等这个连接死亡。触发亡语操作。

#include "writethread.h"WriteThread::WriteThread(int socketdescriptor,QObject *parent):QThread(parent),socketdescriptor(socketdescriptor)
{}void WriteThread::run(){ //多线程执行的函数//QTcpSocket* tcp =new QTcpSocket;    持久化连接{QTcpSocket tcp2; //离开作用域自动释放这条新连接QTcpSocket* tcp =& tcp2;if(!tcp->setSocketDescriptor(socketdescriptor)){emit myerror(tcp->error());  //触发自定义的error信号return;}qDebug()<<"run()";QByteArray data;QDataStream out(&data,QIODevice::WriteOnly);out.setVersion(QDataStream::Qt_5_12);tcp->write(data);}//tcp->disconnectFromHost(); //主动断开与远程主机的TCP连接。
}

主逻辑类

主要实现按钮开启和关闭服务器

#include "dialog.h"
#include "ui_dialog.h"
#include<QMessageBox>
Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog)
{ui->setupUi(this);setWindowTitle("连接计数器服务端");ui->server_ip->setText("127.0.0.1");ui->server_port->setText("8888");icount= 0;tcpserver=new TcpNewConnet(this);}Dialog::~Dialog()
{delete ui;
}void Dialog::slotsdispFunc(){ui->currentv->setText(tr("客户端请求%1次").arg(++icount));
}void Dialog::on_close_clicked()
{//先关闭所有socketif(!tcpserver){tcpserver->disconnect(); //用于断开 QTcpSocket 对象的所有信号与槽的连接。tcpserver->close();      //它会向对端发送 FIN 数据包,并等待对端的确认,完成 TCP 连接的正常关闭过程。//fin回调 已调用 tcpSocket->deleteLater(); //它不会立即删除对象,而是将其标记为待删除状态,等到当前事件循环结束后再执行删除操作。}if(tcpserver->isListening()){tcpserver->close();//不调用 deleteLater 为了下次再次开启ui->listen->setEnabled(true);ui->close->setEnabled(false);QMessageBox::critical(this,tr("提示"),tr("多线程服务器已关闭"));}}void Dialog::on_listen_clicked()
{QString ip(ui->server_ip->text());uint16_t port =ui->server_port->text().toUInt();if(!tcpserver->listen(QHostAddress(ip),port)){tcpserver->close();QMessageBox::critical(this,tr("提示"),tr("多线程服务器已关闭"));return;}QMessageBox::information(this,tr("提示"),tr("多线程服务器已经启动"));ui->listen->setEnabled(false);ui->close->setEnabled(true);
}

总结

通过继承重写和信号槽的方式,可以实现连接建立,断开,发送前,发送后等等操作绑定,重写需要去找指定的重写函数,而信号去找指定的信号名。信号槽机制当绑定多个的时候,是按照绑定的顺序执行,因为底层是信号队列,保证顺序。

如果对信号槽有兴趣,可以看我之前发布的qt 多线程和网络编程文章。

最后附上源代码链接
对您有帮助的话,帮忙点个star

 41-clinet-count · jbjnb/Qt demo - 码云 - 开源中国 (gitee.com)

41-server-count · jbjnb/Qt demo - 码云 - 开源中国 (gitee.com)

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

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

相关文章

从零开始做题:MP3

题目 给出一个mp3文件 解题 右键->selection->save selection->另存为xxx.png即可 8750d5109208213f E:\逐鹿\MISC\tools\MP3Stego_1_1_19\MP3Stego>.\decode -X cipher.mp3 MP3StegoEncoder 1.1.19 See README file for copyright info Input file cipher.mp3…

53-5 内网代理7 - CS上线不出网主机

靶场搭建: 这里就用之前内网代理的靶场,把web服务器这台虚拟机关闭掉,用剩下的3台加kali 各个虚拟机的网络情况 kali - 可以连接外网win2008(之前的FTP服务器) 可以连接外网 win 7(之前的办公电脑) 不出网主机 - 无法连接外网win2012 克隆机(之前的域控) - 无法连接…

视频压缩文件太大了怎么缩小?3个压缩方法分享

视频压缩文件太大了怎么缩小&#xff1f;当视频压缩文件过大时&#xff0c;缩小其大小不仅能节省宝贵的存储空间&#xff0c;还能显著提升文件传输速度&#xff0c;特别是在网络条件有限的情况下。通过专业的视频压缩软件&#xff0c;可以有效减少文件体积&#xff0c;使视频内…

python库(9):prettytable库快速实现ASCII表格

下面介绍一个快速制作ASCII表格库——prettytable&#xff0c;可以方便地制作简单表格。 1 安装prettytable pip install -i https://pypi.tuna.tsinghua.edu.cn/simple prettytable 结果如下&#xff1a; 2 代码实例 from prettytable import PrettyTable table PrettyTa…

【Python系列】深入解析 Python 中的 JSON 处理工具

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

coco数据集格式计算mAP的python脚本

目录 背景说明COCOeval 计算mAPtxt文件转换为coco json 格式自定义数据集标注 背景说明 在完成YOLOv5模型移植&#xff0c;运行在板端后&#xff0c;通常需要衡量板端运行的mAP。 一般需要两个步骤 步骤一&#xff1a;在板端批量运行得到目标检测结果&#xff0c;可保存为yol…

【Django项目】基于Python+Django+MySQL的音乐网站系统项目

功能介绍 首页&#xff1a;歌曲分类、歌曲搜索、热门歌曲、热门下载、新歌推荐 歌曲排行&#xff1a;歌曲分类、分页功能 用户板块&#xff1a;用户登陆/注册、播放历史 歌曲详情&#xff1a;歌曲播放、当前播放列表、歌曲点评、歌曲播放插件、下载歌曲 系统后台&#xff1a;歌…

MySQL体系架构解析

1.MySQL体系架构 1.1.MySQL的分支与变种 MySQL变种有好几个,主要有三个久经考验的主流变种:Percona Server,MariaDB和 Drizzle。它们都有活跃的用户社区和一些商业支持,均由独立的服务供应商支持。同时还有几个优秀的开源关系数据库,值得我们了解一下。 1.1.1.Drizzle …

L2 LangGraph_Components

参考自https://www.deeplearning.ai/short-courses/ai-agents-in-langgraph&#xff0c;以下为代码的实现。 这里用LangGraph把L1的ReAct_Agent实现&#xff0c;可以看出用LangGraph流程化了很多。 LangGraph Components import os from dotenv import load_dotenv, find_do…

2024年高压电工证考试题库及高压电工试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年高压电工证考试题库及高压电工试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人员上岗证考试大纲随机出的高压…

开源项目有哪些机遇与挑战

目录 1.概述 2.开源项目的发展趋势 2.1. 开源项目的发展现状 2.2. 开源社区的活跃度 2.3. 开源项目在技术创新中的作用 3.参与开源的经验分享 3.1. 选择开源项目 3.2. 理解项目结构和文档 3.3. 贡献代码 3.4. 与开源社区的合作 3.5. 学习和成长 4.开源项目的挑战 …

内裤洗衣机到底值不值得买?五大高质量靠谱内衣洗衣机值得拥有

市场上出现了内衣洗衣机&#xff0c;这种洗衣机比市面上的普通洗衣机的清洁力好&#xff0c;还具有除菌功能&#xff0c;在清洗完内衣裤的过程中&#xff0c;可以将衣物上的细菌去除掉&#xff0c;但市面上的内衣品牌众多&#xff0c;什么样的牌子才好用呢&#xff1f;作为一位…

前端简历:如何写项目经历(经验)找出细节点和重难点,轻松应对面试?

&#xff08;下面内容&#xff1a;我将结合我的实际项目带大家进行每一步骤的梳理&#xff09; 项目经历-堂食外送点餐 2022年2月-2022年5月 项目描述&#xff1a;该平台提供外送订餐服务&#xff0c;用户可以在手机中轻松地浏览菜品、下单、支付、编辑地址、填写个人信息等…

手撸俄罗斯方块——游戏设计

手撸俄罗斯方块——游戏设计 概述 上一章我们介绍俄罗斯方块的基本信息&#xff0c;包括坐标点和方块的基本概念&#xff0c;这一章节我们继续介绍如何完成后续的游戏设计。 组成游戏的基本要素 俄罗斯方块作为一个 2D 的平面游戏&#xff0c;我们可以将整个参与元素做如下…

简过网:工程专业最吃香的6个证书,你考了几个了?

工程专业最吃香的6个证书&#xff0c;你考了几个了&#xff1f;我们一起来看看吧&#xff01; 1、二级建造师 报考条件&#xff1a;工程类大专及以上学历/从事相关职业 考试时间&#xff1a;3月报名、6月考试 就业前景&#xff1a;建筑设计院、房产开发公司、施工单位 2、一…

如何管理一百个ai专家智能体——ai调度系统设计

前言 如果你用过openai的chatgpt服务&#xff0c;你肯定知道一个叫做GPTs的智能体商店&#xff0c;里面提供了大量的来自官方和个人制作的专门针对某个领域的gpt助手。比如&#xff0c;你想让gpt帮忙写文章&#xff0c;并且要能够写得好&#xff0c;你就可以在商店中搜索相关的…

Smail语句如何使用判断语句跳过验证卡密界面?谈谈思路

&#x1f3c6;本文收录于《CSDN问答解惑》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&…

数据融合工具(5)面中心线提取

这是一个重磅工具&#xff0c;建议先看视频。 提取中心线 一、需求背景 说真的&#xff0c;当小编第一次使用ArcGIS中的Polygon To Centerline工具提取面要素中心线时&#xff0c;激动得无以言表&#xff0c;毕竟&#xff0c;以前要提取面中心线&#xff0c;是一件非常麻烦的事…

[CTF]-PWN:House of Cat堆题型综合解析

原理&#xff1a; 调用顺序&#xff1a; exit->_IO_wfile_jumps->_IO_wfile_seekoff->_IO_switch_to_wget_mode _IO_wfile_seekoff源码&#xff1a; off64_t _IO_wfile_seekoff (FILE *fp, off64_t offset, int dir, int mode) {off64_t result;off64_t delta, new…

AI绘画小白必备!Stable Diffusion常用插件合集,好用推荐!(附插件下载)

前言 宝子们&#xff0c;早上好啊~Stable Diffusion 常用插件&#xff0c;月月已经给大家整理好了&#xff0c;自取就好。 拥有这些SD常用插件&#xff0c;让您的图像生成和编辑过程更加强大、直观、多样化。以下插件集成了一系列增强功能&#xff0c;覆盖从自动补全提示词到…