QT---day5,通信

server/2024/9/20 15:35:58/

1、思维导图

 2、TCp

服务器
 

#ifndef MYWIDGET_H
#define MYWIDGET_H
 
#include <QWidget>
#include <QTcpServer>
#include <QList>
#include <QTcpSocket>
#include <QMessageBox>
#include <QDebug>
#include <QTcpServer>
 
QT_BEGIN_NAMESPACE
namespace Ui { class MyWidget; }
QT_END_NAMESPACE
 
class MyWidget : public QWidget
{
    Q_OBJECT
 
public:
    MyWidget(QWidget *parent = nullptr);
    ~MyWidget();
 
private slots:
    //void on_pButton_clicked();
 
    void on_startbtn_clicked();
 
    void newConnect_slot();
 
    void readyRead_slot();
 
private:
    Ui::MyWidget *ui;
    QTcpServer *ser;
    QList<QTcpSocket *> cliList;      //客户端容器链表
 
};
#endif // MYWIDGET_H
#include "mywidget.h"
#include "ui_mywidget.h"
 
 
 
MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MyWidget)
{
    ui->setupUi(this);
 
 
    //1、给服务器指针实例化对象
    ser = new QTcpServer(this);
 
 
}
 
 
MyWidget::~MyWidget()
{
    delete ui;
}
 
 
//启动按钮对应的槽函数
void MyWidget::on_startbtn_clicked()
{
    if(ui->startbtn->text() == "启动")
    {
        //获取ui界面上的端口号
        quint16 port = ui->portEdit->text().toUInt();
 
 
 
 
        //启动服务器
        //2、将服务器设置成被动监听状态
        if(ser->listen(QHostAddress::Any, port) == true)
        //参数1:监听的ip地址,如果设置成Any,表示监听所有类型的主机地址,也可以指定特定的主机地址进行监听
        //参数2:端口号,如果设置为0,则让系统自动分配一个端口号,如果使用具体的端口号,则需要指定
        {
            QMessageBox::information(this, "成功", "服务器启动成功");
        }else
        {
            QMessageBox::information(this, "成功", "服务器启动失败");
        }
 
 
        //当启动服务器后,如果有客户端发来连接请求,那么该服务器就会自动发射一个newConnection信号
        //我们可以将该信号,连接到对应的槽函数中处理相关逻辑
        connect(ser, &QTcpServer::newConnection, this, &MyWidget::newConnect_slot);
 
 
 
 
        //将文本内容更改成 关闭
        ui->startbtn->setText("关闭");
    }else
    {
        //关闭服务器
        ser->close();        //关闭监听
 
 
        //将文件内容更改成 启动
        ui->startbtn->setText("启动");
    }
}
 
 
//处理nY
void MyWidget::newConnect_slot()
{
    qDebug () <<"有新客户端发来连接请求了,请尽快处理";
    //获取最新连接的客户端套接字,并将最新连接的套接字地址返回
    QTcpSocket* socket = ser->nextPendingConnection();
 
 
    //将该客户端套接字放入到客户端容器中
    cliList.append(socket);
 
 
    //当有客户端向服务器发来数据时,当前这个客户端套接字就会自动发射一个readyRead信号
    //我们可以将该信号连接到对应的信号处理函数中,处理相关数据
    connect(socket, &QTcpSocket::readyRead, this, &MyWidget::readyRead_slot);
 
 
}
 
 
//关于readyRead信号对应的槽函数的定义
void MyWidget::readyRead_slot()
{
    //判断客户端容器中,是否有已经退出的客户端,或无效的客户端,如果有,将其进行移除
    for(int i=0; i<cliList.length(); i++)
    {
        if(cliList[i]->state() == QTcpSocket::UnconnectedState)
        {//功能:判断当前套接字的状态
           //参数:无
           //返回值:readyRead_slot表示无效的套接字
           cliList.removeAt(i);           //将下标为i的客户端套接字从容器中移除
        }
    }
 
 
    //再将客户端容器遍历一遍,判断哪个客户端中有数据待读
    for(int i=0; i<cliList.length(); i++)
    {
        if(cliList[i]->bytesAvailable() != 0)
        {
            //功能:获取当前套接字中待读数据的个数
            //参数:无
            //返回值:返回套接字中待读数据的个数,如果为0,表示没有数据可读
            //如果不等于0,表示有数据可读,可以使用readAll读取数据
            QByteArray msg = cliList[i]->readAll();
 
 
            //将该消息,展示到ui界面上
            ui->msgWidget->addItem(QString::fromLocal8Bit(msg));
 
 
            //将该消息转发给所有客户端
            for(int j=0; j<cliList.length(); j++)
            {
                if(i!=j)        //不转发给自己
                {
                    cliList[j]->write(msg);
                }
            }
        }
    }
}
 
 

 客户端

 

#ifndef MYWIDGET_H
#define MYWIDGET_H
 
#include <QWidget>
#include <QTcpSocket>
#include <QMessageBox>
 
QT_BEGIN_NAMESPACE
namespace Ui { class MyWidget; }
QT_END_NAMESPACE
 
class MyWidget : public QWidget
{
    Q_OBJECT
 
public:
    MyWidget(QWidget *parent = nullptr);
    ~MyWidget();
 
private slots:
    void on_pushButton_clicked();
    void connnected_slot();
    void readyRead_slot();
 
 
private:
    Ui::MyWidget *ui;
    QTcpSocket *cli;          //定义客户端指针
     QString userName;          //用户名
};
#endif // MYWIDGET_H
 

 

#include "mywidget.h"
#include "ui_mywidget.h"
 
 
MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MyWidget)
{
    ui->setupUi(this);
 
 
    //实例化一个客户端对象
    cli = new QTcpSocket(this);
 
    connect(cli,&QTcpSocket::connected,this,&MyWidget::connnected_slot);
 
    connect(cli,&QTcpSocket::readyRead,this,&MyWidget::readyRead_slot);
 
    //将客户端的connected信号连接到自定义的槽函数中
    connect(cli, &QTcpSocket::connected, this, &MyWidget::connnected_slot);
}
 
MyWidget::~MyWidget()
{
    delete ui;
}
 
 
 
 
 
//连接服务器按钮对应的槽函数
void MyWidget::on_pushButton_clicked()
{
    if(ui->intobtn->text() == "连接服务器")
    {
        //执行连接服务器的工作
        //获取ui界面上的数据
        userName = ui->userNameEdit->text();         //用户名
        QString ip = ui->ipEdit_2->text();            //ip地址
        quint16 port = ui->portEdit->text().toUInt();   //端口号
 
 
        //向服务器发送连接请求
        cli->connectToHost(ip, port);
        //功能:向指定的服务器发送连接请求
        //参数1:服务器ip地址
        //参数2:服务器端口号
 
 
        //当成功连接服务器后,当前客户端会自动发射一个connected的信号,我们可以将该信号连接到对应的槽函数中处理逻辑
        //由于该操作只需进行一次即可,所以写在构造函数中即可
 
 
        //将按钮内容更成 断开服务器
        ui->intobtn->setText("断开服务器");
    }else
    {
 
       QString msg = userName+":离开聊天室";
       cli->write(msg.toLocal8Bit());
 
        //执行断开服务器工作
        cli->disconnectFromHost();
 
        //将按钮内容更改成 连接服务器
         ui->intobtn->setText("连接服务器");
    }
}
 
//处理readyRead信号对应的槽函数的是实现
void MyWidget::readyRead_slot()
{
    QByteArray msg =cli->readAll();
 
    ui->msgWidget->addItem(QString::fromLocal8Bit(msg));
}
 
//自定义处理connnected信号的槽函数的实现
void MyWidget::connnected_slot()
{
    QMessageBox::information(this, "连接", "连接服务器成功!!!");
}
 

 


http://www.ppmy.cn/server/41829.html

相关文章

学习MySQL(二):库表的操作

库的增删改查 增 -- 创建库 create database 库名 charset 字符编码; 删 -- 删除库 drop database 库名; 改 -- 修改字符编码 alter database 库名 charset 字符编码; # 注&#xff1a;一般只改字符编码&#xff0c;数据库名称是不能改的 查 -- 查询当前账户下所有的库…

AppBuilder低代码体验:构建雅思大作文组件

AppBuilder低代码体验&#xff1a;构建雅思大作文组件 ​ 在4月14日&#xff0c;AppBuilder赢来了一次大更新&#xff0c;具体更新内容见&#xff1a;AppBuilder 2024.04.14发版上线公告 。本次更新最大的亮点就是**新增了工作流&#xff0c;低代码制作组件。**具体包括&#x…

正点原子FreeRTOS学习笔记——列表与列表项

目录 一、什么是列表和列表项 1、概念 2、FreeRTOS代码 &#xff08;1&#xff09;列表 &#xff08;2&#xff09;列表项 &#xff08;3&#xff09;迷你列表项 二、列表与列表项初始化 1、列表初始化 2、列表项初始化 三、列表插入与删除列表项 1、原理解释 2、…

AD域服务器巡检指南

Active Directory (AD) 域服务器的巡检对于确保企业网络的安全性和高效运行至关重要。以下是针对AD域服务器巡检的关键活动和其重要性的优化描述&#xff1a; 保证系统安全&#xff1a; AD域服务器储存大量敏感数据&#xff0c;包括用户账户信息、策略和访问权限数据。定期巡检…

构建NFS远程共享存储

nfs-server:10.1.59.237 nfs-web:10..159.218 centos7,服务端和客户端都关闭防火墙和selinux内核防火墙&#xff0c;如果公司要求开启防火墙&#xff0c;那需要放行几个端口 firewall-cmd --add-port2049/tcp --permanent firewall-cmd --add-port111/tcp --permanent firew…

知识付费系统怎么操作的,培训机构怎么用老带新招生呢?

随着暑假竞争的日益剧烈&#xff0c;各类教育培训机构早已准备着各种招生活动&#xff0c;打算进一步进步学校的招生数量。但是也有很多招生问题在搅扰着学校的招生教师&#xff0c;其实一切的招生活动&#xff0c;都必需效劳于重生报名和老生续报!培训机构如何做好老带新招生?…

7集成学习评分卡

集成学习评分卡 学习目标 知道LightGBM基本原理掌握使用lightGBM进行特征筛选的方法1 Gradient Boosting算法回顾 Gradient Boosting 基本原理 训练一个模型m1,产生错误e1针对e1训练一个模型m2,产生错误e2针对e2训练第三个模型m3,产生错误e3 …最终预测结果是:m1+m2+m3+…GB…

Oracle21c数据库普通用户创建及授权,建表,创建存储过程、序列、触发器

一、Oracle数据库错误 ORA-65096 表示你尝试在多租户容器数据库&#xff08;CDB&#xff09;环境中创建一个公共用户&#xff08;common user&#xff09;或角色&#xff0c;但没有使用正确的前缀。在多租户架构中&#xff0c;公共用户的用户名必须以 C## 或 c## 开头。 若想…

【AI智能体】零代码构建AI应用,全网都在喊话歌手谁能应战,一键AI制作歌手信息查询应用

欢迎来到《小5讲堂》 这是《文心智能体平台》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 文心智能体大赛背景创建应用平台地址快速构建【基础配置】…

【Web后端】servlet基本概念

1.ServletAPI架构 HttpServlet继承GenericServletGenericServlet实现了Servlet接口&#xff0c;ServletConfig接口,Serializable接口自定义Servlet继承HttpServlet 2.Servlet生命周期 第一步&#xff1a;容器加载Servlet第二步&#xff1a;调用Servlet的无参构造方法&#xf…

Android 获取已安装应用、包名、应用名、版本号、版本名

1、相关代码 List<ApplicationInfo> installedApps getPackageManager().getInstalledApplications(0);for (ApplicationInfo appInfo : installedApps) {CharSequence getAppName getPackageManager().getApplicationLabel(appInfo);String appNamegetAppName.toStrin…

java(实验拓展)工厂模式和原型模式

工厂模式 简单来说是一种创建型设计模式&#xff0c;它提供了一种创建对象的最佳实践&#xff0c;这种模式提供了一种抽象工厂&#xff0c;通过使用工厂方法来创建对象。工厂方法将对象的创建推迟到子类中&#xff0c;这样就可以实现对象的创建和使用解耦。 一、概念 工厂模…

练习题(2024/5/14)

1四数相加 II 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少个元组 (i, j, k, l) 能满足&#xff1a; 0 < i, j, k, l < nnums1[i] nums2[j] nums3[k] nums4[l] 0 示例 1&#xff1a; 输入&#xff1a;n…

Vue 常见通信

Vue 常见通信 1、父子通信 父传子 props&#xff0c;子传父 events&#xff08;$emit&#xff09;&#xff1b; 通过父链 / 子链 通信$parent / $children&#xff1b; $refs获取ref 可以访问组件实例方法&#xff0c;&#xff1b; 提供与注射provide / inject a t t r s …

vscode切换分支及合并分支操作教程

工具&#xff1a;gitee、git 、vscode、Git Graph 点击可以看到分支管理明细。 一、前提 1、首先要有两个分支 &#xff08;1&#xff09;分支说明&#xff1a; test&#xff1a; 测试分支 feature/luo-20240508&#xff1a;自己的开发分支 &#xff08;2&#xff09;分支说…

npm无法安装node-sass 的问题

安装 node-sass 的问题呈现&#xff1a;4.9.0版本无法下载 Downloading binary from https://github.com/sass/node-sass/releases/download/v4.9.0/win32-x64-72_binding.node Cannot download "https://github.com/sass/node-sass/releases/download/v4.9.0/win32-x64-…

【Git教程】(十八)拆分大项目 — 概述及使用要求,执行过程及其实现,替代解决方案 ~

Git教程 拆分大项目 1️⃣ 概述2️⃣ 使用要求3️⃣ 执行过程及其实现3.1 拆分模块版本库3.2 将拆分出的模块作为外部版本库集成 4️⃣ 替代解决方案 通常软件项目都是由单体小型系统开始的&#xff0c;在开发过程中项目规模和团队人员不断扩大&#xff0c; 将项目模块化会显得…

idea使用gitee基本操作流程

1.首先&#xff0c;每次要写代码前&#xff0c;先切换到自己负责的分支 点击签出。 然后拉取一次远程master分支&#xff0c;保证得到的是最新的代码。 写完代码后&#xff0c;在左侧栏有提交按钮。 点击后&#xff0c;选择更新的文件&#xff0c;输入描述内容&#xff08;必填…

正则表达式和lambda表达式

正则表达式&#xff08;Regular Expressions&#xff09;和Lambda表达式虽然都包含“表达式”一词&#xff0c;但它们在编程中的作用和用法是完全不同的。让我们详细比较一下它们的定义、用途和应用场景&#xff1a; 正则表达式 定义&#xff1a;正则表达式是一种用于匹配文本…

知识分享|XDC时钟约束的详细说明

在FPGA设计中&#xff0c;时钟约束是确保设计满足时序要求的关键。Xilinx Design Constraints (XDC) 文件允许设计者对时钟、输入/输出(I/O)和跨时钟域(CDC)路径进行精确的时序约束。以下是XDC文件中时钟约束的详细说明&#xff1a; 时钟约束的重要性 时钟约束必须最早创建&a…