qt day 5

实现局域网的网络聊天室功能

1>服务器代码

cpp 复制代码
---------------------------------------------------------------
widget.h
---------------------------------------------------------------
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QMessageBox>
#include <QTcpServer>
#include <QTcpSocket>
#include <QPushButton>
#include <QLabel>
#include <QListWidget>
#include <QLineEdit>
#include <QList>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

public slots:
    void connectbtn_slot();
    void connected_slot();
    void readyread_slot();

private:
    Ui::Widget *ui;

    //定义服务器
    QTcpServer *server;

    //定义一个链表存放连接的客户端数据
    QList<QTcpSocket *> client;

};
#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);


    //连接按钮与对应槽函数
    connect(ui->connectbtn,&QPushButton::clicked,this,&Widget::connectbtn_slot);

}

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

//按下按钮后启动服务器
void Widget::connectbtn_slot()
{
    //读取端口号
    quint16 port = ui->portedit->text().toInt();
    //设置为监听状态
    if(!server->listen(QHostAddress::Any,port))
    {
        QMessageBox::critical(this,"失败","服务器启动失败");
        return ;
    }
    QMessageBox::information(this,"成功","服务器启动成功");

    //连接客户端信号与槽函数
    connect(server,&QTcpServer::newConnection,this,&Widget::connected_slot);
}

//客户端连接槽函数
void Widget::connected_slot()
{
    //获取客户端套接字
    QTcpSocket *cli = server->nextPendingConnection();

    //将得到的套接字写入链表
    client.push_back(cli);
    //把新套接字与接收信号连接
    connect(cli,&QTcpSocket::readyRead,this,&Widget::readyread_slot);

}

//有信息写入准备读取
void Widget::readyread_slot()
{
    //删除已经断开的客户端
    for(int i = 0;i < client.size();i++)
    {
        if(client.at(i)->state() == 0)
        {
            client.removeAt(i);
        }
    }

    //遍历发送数据的客户端
    for(int i = 0;i < client.size();i++)
    {
        if(client.at(i)->bytesAvailable() != 0)
        {
            //读取客户端数据
            QByteArray msg = client.at(i)->readAll();
            //将数据写到ui界面中
            ui->listWidget->addItem(QString::fromLocal8Bit(msg));
            //将数据发送给所有客户端
            for(int j = 0;j < client.size();j++)
            {
                client.at(j)->write(msg);
            }
        }
    }

}

2>客户端代码

cpp 复制代码
---------------------------------------------------------------
widget.h
---------------------------------------------------------------
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
#include <QListWidget>
#include <QMessageBox>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

public slots:
    void connectbtn_slot();
    void connected_slot();
    void readyread_slot();
    void sndbtn_slot();
    void disconbtn_slot();
    void disconnect_slot();

private:
    Ui::Widget *ui;

    //定义一个客户端套接字
    QTcpSocket *client;
    //定义一个用户名
    QString username;
};
#endif // WIDGET_H
---------------------------------------------------------------
widget.h
---------------------------------------------------------------
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //为客户端套接字实例化空间
    client = new QTcpSocket(this);
    //连接按钮与对应槽函数连接
    connect(ui->connectbtn,&QPushButton::clicked,this,&Widget::connectbtn_slot);
    //已连接信号与对应槽函数连接
    connect(client,&QTcpSocket::connected,this,&Widget::connected_slot);
    //服务器发送信息信号与对应槽函数连接
    connect(client,&QTcpSocket::readyRead,this,&Widget::readyread_slot);
    //发送按钮与对应槽函数连接
    connect(ui->sndbtn,&QPushButton::clicked,this,&Widget::sndbtn_slot);
    //断开按钮与对应槽函数
    connect(ui->disconbtn,&QPushButton::clicked,this,&Widget::disconbtn_slot);
    //断开连接信号与对应槽函数
    connect(client,&QTcpSocket::disconnected,this,&Widget::disconnect_slot);
    //设置按钮与编辑框可用
    ui->disconbtn->setEnabled(0);
    ui->sndbtn->setEnabled(0);
    ui->msgedit->setEnabled(0);

}

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

//连接按钮槽函数
void Widget::connectbtn_slot()
{
    //从ui界面读取IP与port
    QString IP = ui->IPedit->text();
    quint16 port = ui->portedit->text().toUInt();
    //连接服务器
    client->connectToHost(IP,port);
}

//已连接槽函数
void Widget::connected_slot()
{
    //连接完成提示信息
    QMessageBox::information(this,"成功","成功进入聊天室");
    //发送xx进入聊天室提示给服务器
    username = ui->usernameedit->text();
    QString sndmsg = username + " : 进入聊天室";
    client->write(sndmsg.toLocal8Bit());

    //设置按钮与编辑框可用
    ui->usernameedit->setEnabled(0);
    ui->IPedit->setEnabled(0);
    ui->portedit->setEnabled(0);
    ui->connectbtn->setEnabled(0);
    ui->sndbtn->setEnabled(1);
    ui->msgedit->setEnabled(1);
    ui->disconbtn->setEnabled(1);

}

//读取服务器发送信息
void Widget::readyread_slot()
{
    //读取信息
    QByteArray msg = client->readAll();
    //将读取的信息发送到信息框内
    ui->listWidget->addItem(QString::fromLocal8Bit(msg));
}

//发送按钮对应槽函数
void Widget::sndbtn_slot()
{
    //读取ui界面发送框内信息
    QString msg = ui->msgedit->text();
    msg = username + " : " + msg;
    //将数据发送给服务器
    client->write(msg.toLocal8Bit());
}

//断开连接按钮对应槽函数
void Widget::disconbtn_slot()
{
    //准备发送离开信息
    QString msg = username + " : 离开聊天室";
    client->write(msg.toLocal8Bit());
    //断开连接
    client->disconnectFromHost();
}

//断开连接信号槽函数
void Widget::disconnect_slot()
{
    QMessageBox::information(this,"断开连接","成功退出聊天室");
    //设置按钮与编辑框可用
    ui->usernameedit->setEnabled(1);
    ui->IPedit->setEnabled(1);
    ui->portedit->setEnabled(1);
    ui->connectbtn->setEnabled(1);
    ui->disconbtn->setEnabled(0);
    ui->sndbtn->setEnabled(0);
    ui->msgedit->setEnabled(0);
}
相关推荐
鹅毛在路上了1 小时前
C++, ffmpeg, libavcodec-RTSP拉流,opencv实时预览
c++·opencv·ffmpeg
John_ToDebug1 小时前
定制 ResourceBundle 的实现与 DuiLib 思想在 Chromium 架构下的应用解析
c++·chrome·ui
小欣加油3 小时前
leetcode 面试题01.02判定是否互为字符重排
数据结构·c++·算法·leetcode·职场和发展
王璐WL3 小时前
【c++】c++第一课:命名空间
数据结构·c++·算法
aramae3 小时前
C++ -- 模板
开发语言·c++·笔记·其他
MChine慕青5 小时前
顺序表与单链表:核心原理与实战应用
linux·c语言·开发语言·数据结构·c++·算法·链表
骄傲的心别枯萎6 小时前
RV1126 NO.16:通过多线程同时获取H264和H265码流
linux·c++·音视频·rv1126
落羽的落羽7 小时前
【C++】特别的程序错误处理方式——异常机制
开发语言·c++
空山新雨(大队长)7 小时前
C 语言第一课:hello word c
c++·c·exe
春蕾夏荷_7282977257 小时前
c++ 第三方库与个人封装库
c++·三方库