QT---day5,通信

server/2024/12/2 7:08:32/

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## 开头。 若想…