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();
}
相关推荐
blasit2 天前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
郑州光合科技余经理7 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
feifeigo1237 天前
matlab画图工具
开发语言·matlab
dustcell.7 天前
haproxy七层代理
java·开发语言·前端
norlan_jame7 天前
C-PHY与D-PHY差异
c语言·开发语言
多恩Stone7 天前
【C++入门扫盲1】C++ 与 Python:类型、编译器/解释器与 CPU 的关系
开发语言·c++·人工智能·python·算法·3d·aigc
QQ4022054967 天前
Python+django+vue3预制菜半成品配菜平台
开发语言·python·django
遥遥江上月7 天前
Node.js + Stagehand + Python 部署
开发语言·python·node.js
m0_531237177 天前
C语言-数组练习进阶
c语言·开发语言·算法
Railshiqian7 天前
给android源码下的模拟器添加两个后排屏的修改
android·开发语言·javascript