QT学习day5(QT实现TCP协议)

作业:利用TCP客户端和服务器实现网络聊天室(简单版QQ)

1.服务器代码

widget.h

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QTcpServer>            //服务器头文件
#include<QTcpSocket>             //客户端头文件
#include<QList>                  //链表容器
#include<QMessageBox>            //消息对话框
#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 readyRead_slot();              //自定义处理readyRead信号的槽函数的声明


    
private:
    Ui::Widget *ui;
    //实例化服务对象
    QTcpServer *server;//实例化一个服务器对象
    //创一个存放客户端的套接字的容器
    QList<QTcpSocket *> clientList;
};
#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);

    //给客户端实例化空间
    socket = new QTcpSocket(this);


    //初始化界面(设置不可用)
    ui->msgEdit->setEnabled(false);
    ui->setBtn->setEnabled(false);
    ui->disBtn->setEnabled(false);


    //判断是否连接成功,如果连接成功客户端会自动发射connected,将该信号连接到自定义的槽函数中处理相关的逻辑
    //因为只需要连接一次,所以我们将连接函数写在构造函数中
    connect(socket,&QTcpSocket::connected,this,&Widget::connected_slot);//定义在构造函数是为了只连接一次


    //此时说明服务器和客户端此时已经建立好连接,如果服务器发来数据,该客户端会自动发射readRead信号
    connect(socket,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);

      //判断是否断开成功,如果成功断开连接,客户端自动发射disconnect信号
    connect(socket,&QTcpSocket::disconnected,this,&Widget::dis_slot);

}

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

//链接服务器按钮对应的槽函数
void Widget::on_connectStn_clicked()
{

    //获取ui界面上的IP和端口号
    uesrName=ui->usrnameEdit->text();
    QString ip= ui->ipEdit->text();
    quint16 port=ui->portEdit->text().toUInt();//转换成整型
    //客户端连接链接服务器
    socket->connectToHost(ip,port);




}
//连接成功对应的槽函数实现
void Widget::connected_slot()
{
    //告诉服务器 我来了
    QString msg = uesrName + ":进入聊天室";
    //将信息发送给服务器
    socket ->write(msg.toLocal8Bit());



    //将ui界面上的控价进行相关设置

    ui->usrnameEdit->setEnabled(false);
    ui->ipEdit->setEnabled(false);
    ui->portEdit->setEnabled(false);
    ui->connectStn->setEnabled(false);



    ui->msgEdit->setEnabled(true);
    ui->setBtn->setEnabled(true);
    ui->disBtn->setEnabled(true);


}
void Widget::readyRead_slot()//readyread对应的槽函数
{
    //说明服务器给客户端发来数据
    QByteArray msg = socket->readAll();
    //将数据放入到ui界面中
    ui->listWidget->addItem(QString::fromLocal8Bit(msg));

}

void Widget::dis_slot()
{
    ui->usrnameEdit->setEnabled(true);
    ui->ipEdit->setEnabled(true);
    ui->portEdit->setEnabled(true);
    ui->connectStn->setEnabled(true);



    ui->msgEdit->setEnabled(false);
    ui->setBtn->setEnabled(false);
    ui->disBtn->setEnabled(false);

}


void Widget::on_setBtn_clicked()//发送按钮对应的槽函数处理
{
    //获取ui界面上的文本内容
    QString msg =uesrName+":"+ ui->msgEdit->text();
    //将信息发送给服务器
    socket->write(msg.toLocal8Bit());

    //将msg的文本清空
    ui->msgEdit->clear();

}

void Widget::on_disBtn_clicked()//断开按钮对应的槽函数处理
{
   QString msg = uesrName+":"+ "离开了聊天室,尔等也退下吧";
   socket->write(msg.toLocal8Bit());

   socket->disconnectFromHost();


}

服务器 ui界面:

2.客户端代码

second.h

cpp 复制代码
#ifndef SECOND_H
#define SECOND_H

#include <QWidget>
#include<QIcon>
#include<QTcpServer>//服务器头文件
#include<QTcpSocket>//客户端头文件
#include<QMessageBox>//消息对话框
#include<QDebug>//调试类


namespace Ui {
class Second;
}

class Second : public QWidget
{
    Q_OBJECT
public slots:
    void jump_slot();//接收跳转信号函数

public:
    explicit Second(QWidget *parent = nullptr);
    ~Second();

private slots:
    void on_connectBtn_clicked();//链接服务器对应的槽函数声明
    void connected_solt();
    void readyRead_slot();
    void dis_slot();

    void on_sendBtn_clicked();

    void on_disBtn_clicked();

private:
    Ui::Second *ui;
    //实例化一个客户端对象
    QTcpSocket *socket;

    //定义一个用户名的变量
    QString userName;
};

#endif // SECOND_H

widget.h

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QMovie>//动态图
#include<QPixmap>//图片
#include<QDebug>//输出
#include<QPushButton>//按钮类
#include<QMessageBox>//信息类
#include<QIcon>//图片


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
signals://自定义跳转信号函数
    void jump();

private slots:
    //void on_pushButton_2_clicked();
    void my_slot();//自己定义的槽函数


private:
    Ui::Widget *ui;


};
#endif // WIDGET_H

main.cpp

cpp 复制代码
#include "widget.h"
#include"second.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    //实例化第二个窗口的对象
    Second s;
    QObject::connect(&w,&Widget::jump,&s,&Second::jump_slot);
    return a.exec();
}

second.cpp

cpp 复制代码
#include "second.h"
#include "ui_second.h"

void Second::jump_slot()//跳转信号槽函数
{
    this->show();//将自己的界面进行展示
}

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

    //第二个界面的窗口设置
    this->setWindowTitle("划水摆烂群");
    this->setWindowIcon(QIcon(":/pictrue/eaeb1d87_E780070_63de2b7c.png"));

    //ui->listWidget->setStyleSheet("QListWidget { background-color: transparent; }");//设置背景为透明色


    //给客户端实例化空间
    socket =new QTcpSocket(this);

    //初始化界面(未连接服务器时)
    ui->msgEdit->setEnabled(false);//消息对话框不可用
    ui->sendBtn->setEnabled(false);//发送按钮不可用
    ui->disBtn->setEnabled(false);//离线不可用



    //判断是否连接成功,如果连接成功客户端会自动发射connected,将该信号连接到自定义的槽函数中处理相关的逻辑
    //因为只需要连接一次,所以我们将连接函数写在构造函数中
    connect(socket,&QTcpSocket::connected,this,&Second::connected_solt);//定义在构造函数是为了只连接一次

    //此时说明服务器和客户端此时已经建立好连接,如果服务器发来数据,该客户端会自动发射readRead信号
    connect(socket,&QTcpSocket::readyRead,this,&Second::readyRead_slot);


}


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

void Second::on_connectBtn_clicked()//链接服务器对应的槽函数
{
    //获取ui界面上的IP和端口号
    userName=ui->usernameEdit->text();//获取用户名
    QString ip=ui->ipEdit->text();//获取ip
    quint16 port=ui->portEdit_2->text().toUInt();//获取端口号
    //客户端连接服务器
    socket->connectToHost(ip,port);


}

void Second::connected_solt()//连接成功对应的槽函数
{
    //告诉服务器我上线了
    QString msg = userName + ":已上线";
    //将消息发送给服务器
    socket ->write(msg.toLocal8Bit());

    //重新设置ui界面上的控件
    ui->usernameEdit->setEnabled(false);
    ui->ipEdit->setEnabled(false);
    ui->portEdit_2->setEnabled(false);
    ui->connectBtn->setEnabled(false);



    ui->msgEdit->setEnabled(true);
    ui->sendBtn->setEnabled(true);
    ui->disBtn->setEnabled(true);



}

void Second::readyRead_slot()
{
    //说明服务器给客户端发来数据
    QByteArray msg = socket->readAll();
    //将数据放入到ui界面中
    ui->listWidget->addItem(QString::fromLocal8Bit(msg));
}

void Second::dis_slot()
{
    ui->usernameEdit->setEnabled(true);
    ui->ipEdit->setEnabled(true);
    ui->portEdit_2->setEnabled(true);
    ui->connectBtn->setEnabled(true);



    ui->msgEdit->setEnabled(false);
    ui->sendBtn->setEnabled(false);
    ui->disBtn->setEnabled(false);

}
void Second::on_sendBtn_clicked()//发送按钮对应的槽函数
{
    //获取ui界面上的文本内容
    QString msg =userName+":"+ ui->msgEdit->text();
    //将信息发送给服务器
    socket->write(msg.toLocal8Bit());

    //将msg的文本清空
    ui->msgEdit->clear();

}

void Second::on_disBtn_clicked()//离线按钮对应的槽函数
{
    QString msg = userName+":"+ "离开了聊天室,尔等也退下吧";
    socket->write(msg.toLocal8Bit());

    socket->disconnectFromHost();
}

widget.cpp

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

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

    //窗口图标设计
    this->setWindowTitle("腾讯QQ");
    this->setWindowIcon(QIcon(":/pictrue/20573cf63610bed.jpg"));

    //连接登录Btn信号与槽
    connect(ui->pushButton_2,&QPushButton::clicked,this,&Widget::my_slot);

    ui->zhuceBtn->setStyleSheet("border:1px solid transparent;");
    ui->mimaBtn->setStyleSheet("border:1px solid transparent;");//取消边框

/**********************标签设置****************************/
    //设置标签背景(动态图)
//    QMovie *mv = new QMovie("/*************路径*************/");
//    ui->beijinglabel->setMovie(mv);
//    mv->start();
    //让标签自动使用标签
    ui->beijinglabel->setPixmap(QPixmap(":/pictrue/wKjg2lvGWoCAJlJxAADOBePmF24715.jpg"));
    ui->beijinglabel->setScaledContents(true);

    //设置左上角的标签
//    ui->qqlable->setPixmap(QPixmap(":/pictrue/20573cf63610bed.jpg"));
//    ui->qqlable->setScaledContents(true);
//    ui->qqlable->resize(30,30);//重新设置大小

/**********************登录设置*******************************/






}

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


void Widget::my_slot()//登录按钮对应的槽函数
{
    QString userName =  ui->zhanghaoEdit->text();//获取账号
    QString passWord =  ui->mimaEdit->text();//获取密码


    //判断登录条件是否满足
    if(userName=="admin"&&passWord=="123456")
    {
        //满足登录条件跳转到聊天室页面
//        qDebug() << "deng";
//        this->close();
         emit jump();

        this->hide();//将自己的页面隐藏


    }else
    {
       // qDebug() << "";
        QMessageBox::information(this,"提示:","账号或密码错误请重新输入");
        //ui->zhanghaoEdit->clear();

    }

}

second的ui界面

widget的ui界面

实现效果:

运行出的窗口

密码输入错误弹出的消息对话框和启动服务器成功界面

输入信息上线成功显示界面

消息发送成功界面

离线显示下线信息

相关推荐
潮汐退涨月冷风霜1 小时前
机器学习之非监督学习(四)K-means 聚类算法
学习·算法·机器学习
GoppViper1 小时前
golang学习笔记29——golang 中如何将 GitHub 最新提交的版本设置为 v1.0.0
笔记·git·后端·学习·golang·github·源代码管理
羊小猪~~1 小时前
深度学习基础案例5--VGG16人脸识别(体验学习的痛苦与乐趣)
人工智能·python·深度学习·学习·算法·机器学习·cnn
Charles Ray2 小时前
C++学习笔记 —— 内存分配 new
c++·笔记·学习
我要吐泡泡了哦3 小时前
GAMES104:15 游戏引擎的玩法系统基础-学习笔记
笔记·学习·游戏引擎
骑鱼过海的猫1233 小时前
【tomcat】tomcat学习笔记
笔记·学习·tomcat
贾saisai5 小时前
Xilinx系FPGA学习笔记(九)DDR3学习
笔记·学习·fpga开发
北岛寒沫5 小时前
JavaScript(JS)学习笔记 1(简单介绍 注释和输入输出语句 变量 数据类型 运算符 流程控制 数组)
javascript·笔记·学习
铁匠匠匠7 小时前
从零开始学数据结构系列之第六章《排序简介》
c语言·数据结构·经验分享·笔记·学习·开源·课程设计
架构文摘JGWZ8 小时前
Java 23 的12 个新特性!!
java·开发语言·学习