QT第四讲

思维导图

基于QT的网络聊天室

widget.h

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QTcpServer>          //服务器类
#include<QTcpSocket>          //客户端类
#include<QMessageBox>          //对话框类
#include<QList>                //链表容器
#include<QDebug>           //信息调试类

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_startBtn_clicked();

    void newConnection_slot();   //服务器发出的newConnection信号对应的处理槽函数

    void read_slot();            //服务器将数据发送至客户端界面上的处理槽函数

private:
    Ui::Widget *ui;

    //声明一个服务器指针
    QTcpServer *sever;

    //定义存储客户端容器
    QList<QTcpSocket*> socket_list;

};
#endif // WIDGET_H

widget.cpp

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"

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

    //实例化服务器指针
    sever = new QTcpServer(this);
}

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

//启动按钮对应的槽函数
void Widget::on_startBtn_clicked()
{
    //获取ui界面上的端口信息
    qint16 port = ui->portEdit->text().toUInt();

    if(ui->startBtn->text() == "取消"){
        QMessageBox::information(this,"","即将关闭客户端");
        this->close();
    }

    //设置监听
    if(sever->listen(QHostAddress::Any,port)){ //有客户端发起连接请求
        QMessageBox::information(this,"","服务器已启动");
        ui->startBtn->setText("取消");
    }
    connect(sever,&QTcpServer::newConnection,this,&Widget::newConnection_slot);

}

//服务器发出的newConnection信号对应的处理槽函数
void Widget::newConnection_slot(){
    //获取最新连接的客户端套接字
    //函数原型:virtual QTcpSocket *nextPendingConnection();
    //功能:获取最新连接客户端的套接字
    //参数:无
    //返回值:套接字指针
    QTcpSocket *s = sever->nextPendingConnection();

    socket_list.push_back(s);   //将s存入客户端容器中

    //此时,客户端与服务器已经建立起来连接
    //如果有客户端向服务器发来数据,那么该客户端会自动发射一个readyRead信号
    //我们可以在该信号对应的槽函数中,读取客户端中的数据
    connect(s,&QTcpSocket::readyRead,this,&Widget::read_slot);
}

void Widget::read_slot()
{
    //判断当前客户端是否在连接中
    for (int i = 0;i < socket_list.count();i++) {
        //socketList.at(i)->state();    //任意一个客户端的状态
        //函数原型:SocketState state() const;
        //功能:返回套接字的状态
        //参数:无
        //返回值:套接字状态,是个枚举值,如果为0,表示无效连接
        if(socket_list.at(i)->state() == 0){  //枚举值为0表示不在连接中
            socket_list.removeAt(i);          //从容器中删除
        }
    }

    //判断客户端容器中是否有待读取的数据
    for (int i = 0;i < socket_list.count();i++) {
        //判断当前套接字是否有数据待读
        //函数原型:qint64 bytesAvailable() const override;
        //功能:求出当前套接字中待读数据的个数
        //参数:无
        //返回值:待读数据的个数
        if(socket_list.at(i)->bytesAvailable() != 0){   //表明有数据待读取
            //说明当前套接字中有数据
            //读取当前套接字中的数据
            //函数原型:QByteArray readAll();
            //功能:读取套接字中的所有数据
            //参数:无
            //返回值:QByteArray读取下来的数据
            QByteArray msg = socket_list.at(i)->readAll();

             //将数据展示到ui界面---QString::fromLocal8Bit() <=> inet_ntoa( )
            ui->listWidget->addItem(QString::fromLocal8Bit(msg));//-->字节序列(采用本地的8位编码)转换为字符序列

            //将数据展示给用户
            for (int j = 0;j < socket_list.count();j++) {
                socket_list.at(j)->write(msg);
            }
        }
    }
}

main.cpp

cpp 复制代码
#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}
相关推荐
_凌凌漆_2 小时前
【Qt】Qt中对MVC,MVP的理解
qt
侃侃_天下3 天前
最终的信号类
开发语言·c++·算法
echoarts3 天前
Rayon Rust中的数据并行库入门教程
开发语言·其他·算法·rust
Aomnitrix3 天前
知识管理新范式——cpolar+Wiki.js打造企业级分布式知识库
开发语言·javascript·分布式
每天回答3个问题3 天前
UE5C++编译遇到MSB3073
开发语言·c++·ue5
伍哥的传说3 天前
Vite Plugin PWA – 零配置构建现代渐进式Web应用
开发语言·前端·javascript·web app·pwa·service worker·workbox
小莞尔3 天前
【51单片机】【protues仿真】 基于51单片机八路抢答器系统
c语言·开发语言·单片机·嵌入式硬件·51单片机
我是菜鸟0713号3 天前
Qt 中 OPC UA 通讯实战
开发语言·qt
JCBP_3 天前
QT(4)
开发语言·汇编·c++·qt·算法
Brookty3 天前
【JavaEE】线程安全-内存可见性、指令全排序
java·开发语言·后端·java-ee·线程安全·内存可见性·指令重排序