qt_多人聊天

news2024/10/6 20:26:15

服务器

.pro

QT       += core gui network

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>        //服务器头文件
#include <QTcpSocket>     //客户端头文件
#include <QList>       //客户端容器链表
#include <QMessageBox>
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_btn_clicked();
    void newConnection_slot(); //自定义处理ne'w'con'nect的信号槽函数
    void readyRead_slot();
private:
    Ui::Widget *ui;
    //定义服务器指针
    QTcpServer *server;
    //定义客户端容器,存放的是客户端指针
    QList<QTcpSocket*> clientList;
};

#endif // WIDGET_H

widget.cpp

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

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    //实例化一个服务器
    server = new QTcpServer(this);       //此时服务器已经搭建完毕(类似套接字创建完成)
    this->setWindowTitle("vivi_ser");
    this->setWindowIcon(QIcon("C:/app/QQ/qq.png/account"));
}

Widget::~Widget()
{
    delete ui;
}
//启动服务器按钮对于的槽函数
void Widget::on_btn_clicked()
{
    //获取ui界面上的端口号
    quint16 port = ui->idt->text().toUInt();
    //需要将服务器设置为监听状态
  //  server->listen(QHostAddress::Any,port);
    if(server->listen(QHostAddress::Any,port) == true)
    {
        QMessageBox::information(this,"成功","服务器打开成功");
    }
    else {
        QMessageBox::information(this,"失败","服务器打开失败");
    }
    //将该信号链接到自定义槽函数中,处理相关逻辑
    connect(server,&QTcpServer::newConnection,this,&Widget::newConnection_slot);
}
//处理newconnect信号槽函数实现
void Widget::newConnection_slot()
{
    //获取最新链接的客户端套接字
    QTcpSocket *w = server->nextPendingConnection();
    //将套接字放入套接字链表中
    clientList.push_back(w);
    //此时已经成功将服务器和客户端建立起链接
    //这时,如果该客户端向服务器发送数据,该客户端会自动发送一个readRead信号
    //我们可以将该信号链接到自定义槽中,处理发送来的数据
    connect(w,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);
}
//处理readyRead信号的槽函数的实现
void Widget::readyRead_slot()
{
    //清理链表中无效客户端链接
    for(int i = 0;i <clientList.size();i++)
    {
        //找到任意一个客户端:clientList.at(i)
        //判断当前套接字是否有效
        if(clientList.at(i)->state() == 0)   //0表示无效链接
        {
            //将该套接字移除链表
            clientList.removeAt(i);
        }
    }
    //判断是哪个客户端发送来的数据
    for(int i = 0;i<clientList.count();i++)
    {
        //判断当前套接字中是否有可读数据
        if(clientList.at(i)->bytesAvailable() != 0)   //不为0 说明有数据可读
        {
            //将该套接字中的数据读取出来
            QByteArray msg = clientList.at(i)->readAll();
            //将该数据展示到ui界面上
            ui->msg->addItem(QString::fromLocal8Bit(msg));
            //将获取的数据转发给所有客户端
            for(int i = 0;i<clientList.count();i++)
            {
                clientList.at(i)->write(msg);
            }
        }
    }

}

客户端

.pro

QT       += core gui network

widget.h

 

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>   //客户端套接字
#include <QMessageBox>   //

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_btn2_clicked();
    void connected_slot();   //处理connected槽函数
    void readyRead_slot(); //处理readyRead信号槽函数

    void on_btn1_clicked();
    void disconnected_slot();

private:
    Ui::Widget *ui;
    //定义客户端套接字指针
    QTcpSocket *socket;
    //用户名
    QString userName;
};

#endif // WIDGET_H

widget.cpp

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

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("vivi_cer");
    this->setWindowIcon(QIcon("C:/app/QQ/qq.png/lala"));
    //实例化一个客户端对象
    socket = new QTcpSocket(this);
    //此时 如果链接服务器成功,客户端会自动发送一个connectted信号
    //将信号链接到对应的槽函数函数处理
    //只需要链接一次,将该链接放在构造函数中
    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;
}
//连接服务器按钮对应的槽函数
void Widget::on_btn2_clicked()
{
    //获取ui界面上的ip 端口号 用户名
    userName = ui->lineEdit_name->text();
    QString ip = ui->lineEdit_ipsdress->text();
    quint16 port =ui->lineEdit_id->text().toUInt();
    if(ui->btn2->text() == "链接服务器")
    {
        //执行链接服务器的逻辑
        socket->connectToHost(ip,port);
        //此时 如果链接服务器成功,客户端会自动发送一个connectted信号
        //将信号链接到对应的槽函数函数处理
        //只需要链接一次,将该链接放在构造函数中

        //将按钮文本内容改成断开连接
        ui->btn2->setText("断开链接");
    }
    else {
        //告诉大家我走了
        QString msg = userName+"断开连接";
        socket->write(msg.toLocal8Bit());
        //执行断开连接功能
        socket->disconnectFromHost();
        //将按钮文本内容改成连接服务器
         ui->btn2->setText("链接服务器");
    }
}
//有关处理connected槽函数的实现
void Widget::connected_slot()
{
    QMessageBox::information(this,"成功","链接服务器成功");
    //向服务器发送一条消息 说明谁来了
    QString msg;
    msg = userName + ":进入群聊";
    //将该消息发送给服务器
    socket->write(msg.toLocal8Bit());
}
//有关readyRead槽函数实现
void Widget::readyRead_slot()
{
    //将套接字的数据读取出来
    QByteArray msg = socket->readAll();
    //将该信息展示到ui界面上
    ui->ui_mag->addItem(QString::fromLocal8Bit(msg));

}
//发送按钮对应的槽函数
void Widget::on_btn1_clicked()
{
    //获取ui界面中要发送的文本内容
    QString sendMsg = ui->lineEdit_sendcontent->text();
    //将数据整改
    sendMsg = userName + ":" + sendMsg;
    //将消息发送给服务器
    socket->write(sendMsg.toLocal8Bit());
    //将编辑文本内容清空
    ui->ui_mag->clear();
}
//处理disconnected信号槽函数实现
void Widget::disconnected_slot()
{
    QMessageBox::information(this,"信息","退出成功");
}

result

 

 

 

 

 

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

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

相关文章

【SpringMVC】SSM整合

1&#xff0c;SSM整合 前面我们已经把Mybatis、Spring和SpringMVC三个框架进行了学习&#xff0c;今天主要的内容就是把这三个框架整合在一起完成我们的业务功能开发&#xff0c;具体如何来整合&#xff0c;我们一步步来学习。 1. 流程分析 (1) 创建工程 创建一个Maven的web…

【IE】浏览器兼容问题IE

IE11浏览器 1.安装npm i babel-polyfill -S 2.main.js引入&#xff1a; import “babel-polyfill” 3.build/webpack.base.conf.js 更改 : entry: { app: [‘babel-polyfill’, ‘./src/main.js’] } 以上操作之后IE11依旧空白&#xff0c;报错 缺少标识符 axios版本V1.1.3 …

手把手教你搭建一个vue3+ts项目(超祥/必看)

目录 一、创建vite项目 二、启动vite项目 三、处理一些配置问题 四、增加工程化插件 1、安装sass 2、安装vue-router 3、安装pinia 4、安装element-plus 5、安装axios 6、设置路径别名&#xff0c;将相对路径改为绝对路径 一、创建vite项目 1、在一个文件夹下通…

React基础教程(二):React的基本使用

React基础教程(二)&#xff1a;React的基本使用 1、HelloReact 1.1 引入react基础依赖包 注意点&#xff1a;①必须要在②之前引入 <!-- 引入react核心库--><script src"../js/react.development.js"></script><!-- 引入react-dom&…

毕业论文里引用文献率为0%的解决小技巧

快要毕业了&#xff0c;带着伤感&#xff0c;大学生们已开始加紧完成论文的编写和毕业答辩&#xff0c;祝大家都可以顺利拿到学位证书和毕业证书。 前两天&#xff0c;有位同学找我&#xff0c;咨询如何解决毕业论文里&#xff0c;引用文献率为0%的问题。 我在知网上将该论文通…

flutter创建、安装扩展包、打包apk

1、创建APK项目 要在VSCode中创建一个Flutter应用程序&#xff0c;请按照以下步骤进行操作&#xff1a; 安装Flutter SDK&#xff1a;请确保你已经安装了Flutter SDK&#xff0c;并配置了Flutter的环境。你可以在Flutter的官方网站上找到安装和设置Flutter的详细说明。 安装V…

完美解决 RabbitMQ 可视化界面中 Overview 不显示图形的问题

&#x1f4a7; 记录一下今天遇到的 b u g \color{#FF1493}{记录一下今天遇到的bug} 记录一下今天遇到的bug&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主页——微风撞见云的博客&#x1f390; &#x1f433; 数据结构与算法…

VBA基础(宏编程)

VBA介绍&#xff1a; Visual Basic for Applications&#xff08;VBA&#xff09;是 VisualBasic 的一种宏语言&#xff0c;是微软开发出来在其桌面应用程序中执行通用的自动化(OLE)任务的编程语言。主要能用来扩展 Windows 的应用程序功能&#xff0c;特别是Microsoft Office…

DolphinDB +机器学习,预测地震波形数据

1. 地震波形数据预测业务场景说明 在地震波形数据异常检测场景中&#xff0c;通常需要使用多种工具和方法来提高检测精度和鲁棒性。其中&#xff0c;FilterPicker 是一种常用的基于模板匹配的异常检测工具&#xff0c;可以实现地震波形数据的实时异常检测和定位。FilterPicker…

为什么看了那么多测试技术帖,自己都没有提升?

作为测试新手&#xff0c;最爱莫过于看各大牛发的技术贴&#xff0c;这篇很牛叉&#xff0c;那篇也很有道理&#xff0c;似乎自己看着看着也会成为高手。然而几年后&#xff0c;发现自己对专业知识的理解乱的很&#xff0c;里面更有很多自相矛盾的地方&#xff0c;这到底是哪里…

RedisSon高并发分布式锁实战

Redis高并发分布式锁实战 1.分布式场景下的synchronized失效的问题–用redis实现分布式锁 synchronized是通过monitor实现的jvm级别的锁&#xff0c;如果是分布式系统&#xff0c;跑在不同的虚拟机上的tomcat上&#xff0c;会导致synchronized无法锁住对象 ----------- 需要分…

01分数规划 易懂+例题讲解 (c++)

01分数规划 &#xff1a;01即取还是不取&#xff0c;分数即所求型式为&#xff0c;规划就是选取最好的方案。 一般情况题目给出n个物品&#xff0c;再给出每个物品的价值以及物重&#xff0c;选取k个物品&#xff0c;问你在所有可能选取的方案中&#xff0c;最大的单位价值为多…

通过零代码ETLCloud实现马帮ERP数据自动化同步

马帮ERP介绍 马帮ERP是一款云端跨境电商管理软件。与传统的ERP系统不同&#xff0c;马帮ERP专注于跨境电商领域&#xff0c;为电商企业提供一站式管理解决方案&#xff0c;包括财务管理、采购管理、进销存管理、订单管理等功能模块。该平台针对跨境电商行业特点&#xff0c;提…

MM32F3273G8P火龙果开发板MindSDK开发教程20 - freertos + letter shell 的移植

MM32F3273G8P火龙果开发板MindSDK开发教程20 - freertos letter shell 的移植 1、freertos下载 官网传送门 2、freertos移植 1、在工程目录device下新建freertos目录&#xff0c;将下载的源码source目录下的七个.c文件copy到新建的freertos目录。 2、将source/protable/G…

Word 2021入门指南:详细解读常用功能

软件安装&#xff1a;办公神器office2021安装教程&#xff0c;让你快速上手_正经人_____的博客-CSDN博客 一、 新建文档 打开Word 2021后&#xff0c;可以看到左上角的“文件”选项&#xff0c;点击它&#xff0c;在弹出的菜单中选择“新建”选项。然后可以选择空白文档或者使…

vue3+ts+vite+element plus中使用luckysheet(预览效果)

前言&#xff1a; 这两天一个项目&#xff0c;需要在页面中以excel的形式展示大量数据&#xff0c;喜欢偷懒的我果断扒拉了一堆适用于vue3的插件&#xff0c;下面简单说说我使用的luckysheet 使用&#xff1a; 一、准备一个vue3tsviteelement plus的项目 此处省略n个字。。。…

如何用 WampServer+快解析 搭建php文件管理器

基于网络&#xff0c;资源是大家最最基本的需求&#xff0c;许多网络爱好者不求利益&#xff0c;把自己收集的一些通过一些平台共享给大家&#xff0c;这就是资源共享。 资源共享程度越高&#xff0c;代表信息发展水平越高。现实工作中&#xff0c;由于用户提供的数据可能来自…

Linux基础IO - 软硬链接 | 动静态库

之前的文章中我们讲述了软硬链接中有关软连接的知识&#xff0c;本文中将继续讲述硬链接部分的知识&#xff0c;并且讲述一下动静态库的相关内容。 硬链接 硬链接本质上就是在当前目录建立一个新的文件名与指定文件inode的关系。 每当我们在当前目录下建立一个硬链接就会让文…

C++11多线程之条件变量

文章目录 一、关于多线程的同步二、初始条件变量三、关于条件变量的例题四、生产者消费者模型 一、关于多线程的同步 //函数被调用&#xff0c;分配相应的栈帧&#xff0c;进行现场保护void func(char c) {char filename[20] {};sprintf(filename, "test%c.txt",c)…

Fiddler Response私人订制

在客户端接口的测试中&#xff0c;我们经常会需要模拟各种返回状态或者特定的返回值&#xff0c;常见的是用Fiddler模拟各种请求返回值场景&#xff0c;如重定向AutoResponder、请求拦截修改再下发等等。小编在近期的测试中遇到的一些特殊的请求返回模拟的测试场景&#xff0c;…