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);
}
相关推荐
qmx_0719 分钟前
MFC -文件类控件
c++·mfc
Sunsets_Red1 小时前
Linux 系统
linux·运维·服务器·c++·学习·系统架构·系统安全
程序猿练习生1 小时前
C++速通LeetCode中等第18题-删除链表的倒数第N个结点(最简单含注释)
c++·leetcode·链表
极地星光1 小时前
设计模式-适配器模式
c++·设计模式·适配器模式
mljy.2 小时前
STL简介
c++·学习
职创未来官方2 小时前
大话C++:第11篇 类的定义与封装
c++·面向对象·封装··嵌入式物联网·访问修饰符
田小呱2 小时前
C/C++事件驱动的业务框架
c语言·c++
蠢蠢的打码2 小时前
8587 行编辑程序
数据结构·c++·算法·链表
农大蕉蕉2 小时前
C++校招面经(二)
java·开发语言·c++
维生素C++2 小时前
【可变模板参数】
linux·服务器·c语言·前端·数据结构·c++·算法