8.21 QT

news2024/11/27 4:32:04

1.思维导图

2.

服务器端

头文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>//服务器类
#include <QMessageBox>
#include <QDebug>
#include <QList>
#include <QTcpSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

public slots:
    void newConnection_slot();
    void readyRead_slot();

private slots:
    void on_start_btn_clicked();

private:
    Ui::Widget *ui;

    //实例化一个服务器只针对象
    QTcpServer *server;

    QList <QTcpSocket *> socketList;
};
#endif // WIDGET_H

源文件

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    , server(new QTcpServer(this))//给服务器指针对象实例空间
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

//newConnection信号对应的槽函数实现
void Widget::newConnection_slot()
{
    qDebug() << "有新的客户端连接。。";

    //使用nextPaddingConnection() 获取最新连接客户端的套接字
    QTcpSocket *s = server->nextPendingConnection();

    //将客户端放入容器中
    socketList.push_back(s);

    //程序运行至此,说明客户端和服务器成功建立了连接,
    //就可以将该信号连接到自定义的槽函数中,读取发来的数据
    connect(s,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);
}

//readyRead()信号对应的槽函数
void Widget::readyRead_slot()
{
    //读取客户端发来的数据

    //遍历客户端容器,移除无效客户端
    for (int i=0;i<socketList.count();i++)
    {
        //判断客户端和服务器的连接状态
        //SocketState state() const;
        //客户端和服务器未连接的枚举值是0
        if(socketList.at(i)->state() == 0)
        {
            //移除无效客户端
            socketList.removeAt(i);
        }
    }
    //遍历所有在线的客户端,找出待读数据的客户端
    for (int i = 0; i<socketList.count(); i++)
    {
        //判断哪个客户端有数据待读
        if(socketList.at(i)->bytesAvailable() !=0)
        {
            //读取数据
            QByteArray msg = socketList.at(i)->readAll();

            //将读取到的数据放入ui界面上
            ui->listWidget->addItem(QString::fromLocal8Bit(msg));

            //将数据广播给所有客户端
            for (int j=0;j<socketList.count();j++)
            {
                socketList.at(j)->write(msg);
            }
        }
    }
}

//启动服务器按钮对应的槽函数
void Widget::on_start_btn_clicked()
{
    //获取ui界面上的端口号
    quint16 port = ui->portEdit->text().toUInt();//将字符串转换为整型

    //服务器设置监听
    //bool listen(const QHostAddress &address = QHostAddress::Any,quint16 port=0);
    //参数1:监听的主机
    //参数2:监听的端口号
    //返回值:监听成功返回true  否则false
    if(server->listen(QHostAddress::Any,port))
    {
        //监听成功
        QMessageBox::information(this,"","启动服务器成功!");
    }
    else
    {
        //监听失败
        QMessageBox::information(this,"","启动服务器失败!");
        return;
    }
    //此时如果有客户端发来连接请求,那么服务器就会自动发射一个newConnection()信号
    //将该信号连接到自定义的槽函数中,处理逻辑代码
    connect(server,&QTcpServer::newConnection,this,&Widget::newConnection_slot);


}

客户端

头文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>
#include <QMessageBox>
#include <QVBoxLayout>


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_connectbtn_clicked();
    void on_sendbtn_clicked();

    void on_breakbtn_clicked();

public slots:
    void connected_slot();
    void readyRead_slot();
    void disconnected_slot();

private:
    Ui::Widget *ui;

    QTcpSocket *socket;

    //
    QString userName;
};
#endif // WIDGET_H

源文件

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    , socket(new QTcpSocket(this))
{
    ui->setupUi(this);

    //初始化界面
    ui->msgEdit->setEnabled(false);
    ui->sendbtn->setEnabled(false);
    ui->breakbtn->setEnabled(false);

    //如果成功连接到服务器,那么客户端就会自动发射一个connected()信号
    //我们就可以将该信号连接到自定义的槽函数中处理逻辑代码,由于只需要连接一次,所以连接函数写在构造函数中
    connect(socket, &QTcpSocket::connected, this, &Widget::connected_slot);

    //程序运行至此,说明客户端成功与服务建立连接,如果服务器发来数据,那么客户端就会自动发射一个readyRead()信号
    //我们就可以将该信号连接到自定义的槽函数,读取数据。由于只需连接一次,所以连接函数写在构造函数中
    connect(socket, &QTcpSocket::readyRead, this, &Widget::readyRead_slot);

    //如果成功断开与服务器的连接,那么客户端就会自动发射一个disconnected的信号
    //我们就可以将该信号连接到自定义的槽函数,。由于只需连接一次,所以连接函数写在构造函数中
    connect(socket,&QTcpSocket::disconnected,this,&Widget::disconnected_slot);
}

Widget::~Widget()
{
    delete ui;
}

//readyRead()信号对应的槽函数
void Widget::readyRead_slot()
{
    static int row=0;

    //读取服务器发来的数据
    QByteArray msg = socket->readAll();

    //拆分出用户名
        QStringList list = (QString::fromLocal8Bit(msg)).split(":");

        //将数据放入ui界面上
        ui->listWidget->addItem(QString::fromLocal8Bit(msg));

        //根据用户名设置显示位置
        if(list[0]==userName)
        {
            //是本人的消息    靠右显示
            ui->listWidget->item(row)->setTextAlignment(Qt::AlignRight);
        }else
        {
            //不是本人的消息    靠左显示
            ui->listWidget->item(row)->setTextAlignment(Qt::AlignLeft);
        }

        if(list[1]=="离开聊天室"||list[1]=="进入聊天室")
        {
            //居中显示
            ui->listWidget->item(row)->setTextAlignment(Qt::AlignCenter);
        }
   row++;
}

//connected()信号对应的槽函数
void Widget::connected_slot()
{
    userName = ui->userNameEdit->text();
    QString msg = userName + ":进入聊天室";

    //将信息发送服务器
    socket->write(msg.toLocal8Bit());

    //连接服务器成功
    QMessageBox::information(this,"","连接成功!");

    //组件可用的相关设置
    ui->msgEdit->setEnabled(true);
    ui->sendbtn->setEnabled(true);
    ui->breakbtn->setEnabled(true);

    ui->userNameEdit->setEnabled(false);
    ui->ipEdit->setEnabled(false);
    ui->portEdit->setEnabled(false);
    ui->connectbtn->setEnabled(false);

    //程序运行至此,说明客户端成功与服务建立连接,如果服务器发来数据,那么客户端就会自动发射一个readyRead()信号
    //我们就可以将该信号连接到自定义的槽函数,读取数据。由于只需连接一次,所以连接函数写在构造函数中
}

//disconnected()信号对应的槽函数
void Widget::disconnected_slot()
{
    //组件可用的相关设置
    ui->msgEdit->setEnabled(false);
    ui->sendbtn->setEnabled(false);
    ui->breakbtn->setEnabled(false);

    ui->userNameEdit->setEnabled(true);
    ui->ipEdit->setEnabled(true);
    ui->portEdit->setEnabled(true);
    ui->connectbtn->setEnabled(true);

}

//发送按钮对应的槽函数
void Widget::on_sendbtn_clicked()
{
    //获取ui界面的信息
    QString msg = ui->msgEdit->text();

    msg = userName + ":" + msg;

    //发送给服务器
    socket->write(msg.toLocal8Bit());

    //清空行编辑器
    ui->msgEdit->clear();
}

//连接服务器按钮对应的槽函数
void Widget::on_connectbtn_clicked()
{
    //获取ui界面上的IP和端口号
    QString ip = ui->ipEdit->text();
    quint16 port = ui->portEdit->text().toUInt();

    //让客户端连接服务器
    //virtual void connectToHost(const QHostAddress &address, quint16 port, OpenMode mode = ReadWrite);
    //参数1:服务器的ip地址
    //参数2:端口号
    socket->connectToHost(ip,port);

    //如果成功连接到服务器,那么客户端就会自动发射一个connected()信号
    //将该信号连接到自定义的槽函数,书写逻辑代码。由于只需要连接一次,所以连接函数写在构造函数中

}

//断开连接按钮对应的槽函数
void Widget::on_breakbtn_clicked()
{
    QString msg = userName + ":离开聊天室";

    socket->write(msg.toLocal8Bit());

    //断开与服务器的连接
    //virtual void disconnectFromHost();
    socket->disconnectFromHost();

    //如果成功断开与服务器的连接,那么客户端就会自动发射一个disconnected的信号
    //我们就可以将该信号连接到自定义的槽函数,。由于只需连接一次,所以连接函数写在构造函数中
}

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

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

相关文章

免费高画质提取PPT/Word/Excel中的图片工具

下载地址&#xff1a;https://pan.quark.cn/s/134ccc35b8a2 软件简介&#xff1a; 好不容易搞到一个几十上百MB的ppt&#xff0c;想导出里面的图片进行二次加工&#xff0c;却被ppt超低画质的图片另存为功能劝退&#xff0c;明知里面全是高清图片&#xff0c;走时却是两手空空…

【C++从练气到飞升】14---深入浅出继承

&#x1f388;个人主页&#xff1a;库库的里昂 ✨收录专栏&#xff1a;C从练气到飞升 &#x1f389;鸟欲高飞先振翅&#xff0c;人求上进先读书&#x1f389; 目录 ⛳️推荐 一、继承的概念及定义 1.1 继承的概念 1.2 继承定义 1.2.1 定义格式 1.2.2 继承方式和访问限定符…

重新认识AbstractQueuedSynchronizer

开篇之前&#xff0c;烦请诸位允许我附庸风雅一次。近期因诸事繁杂&#xff0c;心情颇低落&#xff0c;遂于喜马拉雅APP中收听《老子》一文。其中的第八十一章《结天道》一文于我感悟颇深&#xff1a;和大怨&#xff0c;必有余怨&#xff0c;报怨以德&#xff0c;焉可以为善&am…

C++,std::bind 详解

文章目录 1. 概述2. 基本用法2.1 使用占位符2.2 示例 3. 总结 1. 概述 std::bind 是 C11 引入的一个功能&#xff0c;它允许你将函数&#xff08;或成员函数、函数对象&#xff09;与其参数绑定&#xff0c;生成一个新的可调用对象。这个功能在需要将函数及其参数一起传递给其…

DNF攻略:护石符文体系辅助详解,VMOS云手机助攻核心玩法!

在DNF游戏中&#xff0c;护石符文系统是提升角色实力的重要部分。当前版本中&#xff0c;护石符文体系经过了优化&#xff0c;使得获取方式更加便捷。以下是护石符文体系的详细介绍&#xff0c;以及如何使用VMOS云手机来更高效地管理和利用这一系统。 一、护石符文体系简介 护…

HarmonyOS 地图服务:深度解析其丰富功能与精准导航实力

目录 前期准备打造个性化地图&#xff1a;聚焦创建地图功能导入Map Kit相关模块通过MapOptions初始化地图切换地图类型设置地图中心点及层级展示定位按钮展示比例尺指定地图的日间夜间模式 通过MapComponentController对象方法控制地图切换地图类型开启3D建筑图层在指定的持续时…

【安当产品应用案例100集】008-UKEY在工业自动化数据传输中应用

工业自动化中的数据传输是确保生产过程高效、稳定运行的关键环节。工业自动化系统中&#xff0c;一般会有一个远程的客户端&#xff0c;负责将各个传感器、控制器等设备产生的信息传递到服务端&#xff0c;以实现生产过程的自动化控制和监控。它对于提高生产效率、降低生产成本…

SQL Server 2017上服务端设置强制加密启用SSL

在数据库服务端设置&#xff0c;强制所有客户端使用 SSL&#xff0c;设置完后&#xff0c;后续客户端所有连接&#xff0c;都将以密文传送&#xff0c;不论客户端是否指定安全连接&#xff08;即EncryptTrue/False&#xff09; 一、服务端强制加密使用 SSL 1.在数据库服务器上…

C++ 模板进阶知识

目录 一. 非类型模板参数 与类型模板参数确认的区别 何时确认 确认方式 二. 模板的特化 1. 概念 2. 函数模板特化 3. 类模板特化 3.1 全特化 3.2 偏特化 (1). 部分特化 (2). 进一步限制 4. 实际应用 三. 模板分离编译 1. 概念 2. 模板的分离编译 3. 解决方法 四…

【学习笔记】STM32F407探索者HAL库开发(一)STM32F4资源概要

【学习笔记】STM32F407探索者HAL库开发&#xff08;一&#xff09;STM32F4资源概要 1 硬件资源2 STM32命名规则3 STM32数据手册3.1 数据手册各章节内容概要3.2 引脚分布3.3 引脚定义3.4 引脚定义表的具体说明 1 硬件资源 STM32F407ZGT6具体的 内部资源如表 资源数量资源数量内…

鸿蒙Harmony实战开发:Touchscreen驱动器件硬件接口使用实例

功能简介 Touchscreen驱动用于驱动触摸屏使其正常工作&#xff0c;该驱动主要完成如下工作&#xff1a;对触摸屏驱动IC进行上电、配置硬件管脚并初始化其状态、注册中断、配置通信接口&#xff08;I2C或SPI&#xff09;、设定Input相关配置、下载及更新固件等操作。 在HDF&am…

考试:数据库系统(01)

数据库系统 ◆数据&#xff1a;是数据库中存储的基本对象&#xff0c;是描述事物的符号记录。 数据的种类&#xff1a;文本、图形、图像、音频、视频、学生的档案记录、货物的运输 情况等。 ◆数据库DB: 是长期存储在计算机内、有组织的、可共享的大量数据的集合。 ◆数据库…

安恒信息总裁宋端智,辞职了!活捉一枚新鲜出炉的餐饮人!

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》http://mp.weixin.qq.com/s?…

雅菲奥朗 FinOps 认证培训:开启企业云财务管理转型之路

前言&#xff1a; 在当今快速变化的商业环境中&#xff0c;企业面临着前所未有的IT财务挑战。随着云计算和数字化转型的推进&#xff0c;传统的财务管理方式已经不能满足“企业上云”的需求。FinOps&#xff0c;即“云财务管理”应运而生&#xff0c;成为帮助企业实现IT财务流…

Compose TextField详解

首先明确Compose TextField的底层依赖是&#xff1a; TextField BasicTextField CoreTextField 相较于Text&#xff0c;TextField需要提供可输入的能力以及渲染效果动态更新的能力。 // CompositionLocals// If the text field is disabled or read-only, we should not d…

智能菜谱推荐系统_ct3p7

TOC springboot575智能菜谱推荐系统_ct3p7--论文 第一章 概述 1.1 研究背景 近些年&#xff0c;随着中国经济发展&#xff0c;人民的生活质量逐渐提高&#xff0c;对网络的依赖性越来越高&#xff0c;通过网络处理的事务越来越多。随着智能菜谱推荐管理的常态化&#xff0c…

F1 F4 Fn lock 指示灯不亮 联想笔记本 thinkpad

问题描述&#xff1a;F1 F4 Fn lock 指示灯开机的时候亮&#xff0c;但是使用的时候虽然能够发挥正常功能&#xff0c;但是指示灯一直熄灭&#xff0c;指示灯不亮。 电脑型号&#xff1a;联想笔记本 thinkpad E14 Gen 2 。本方案应该适用于所有联想电脑。 解决方法&#xff1a;…

嵌入式和单片机有什么区别?

目录 &#xff08;1&#xff09;什么是嵌入式&#xff1f; &#xff08;2&#xff09;什么是单片机&#xff1f; &#xff08;3&#xff09;嵌入式和单片机的共同点 &#xff08;4&#xff09;嵌入式和单片机的区别 &#xff08;1&#xff09;什么是嵌入式&#xff1f; 关…

掉毛不愁!浮毛怎么去掉比较干净?这宠物空气净化器用上真能解决

这阵子天气热得让人只想宅家&#xff0c;门窗紧闭&#xff0c;空调一开就是一整天。室内凉爽宜人&#xff0c;但一出门再回来&#xff0c;那满屋的浮毛和异味简直让人措手不及&#xff0c;仿佛从天堂跌入地狱。幸好&#xff0c;我家有台宠物空气净化器这位“救星”&#xff0c;…

【Linux】线程控制|POSIX线程库|多线程创建|线程终止|等待|线程分离|线程空间布局

目录 ​编辑 POSIX线程库 多线程创建 独立栈结构 获取线程ID pthread_self 线程终止 return终止线程 pthread_exit pthread_cancel 线程等待 退出码问题 线程分离 测试 线程ID及地址空间布局 ​编辑 POSIX线程库 pthread线程库是 POSIX线程库的一部分&#xf…