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

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

1.服务器代码

widget.h

#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_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic: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

#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

#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 

 

#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_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic: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

#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

#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();//获取ipquint16 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

#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界面 

 

实现效果: 

运行出的窗口

 

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

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

 消息发送成功界面

离线显示下线信息

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/167734.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“香蕉大王”的转型升级,能否扩大市场份额?

佳农食品控股 ( 集团 ) 股份有限公司,于2023年10月11日同海通证券签署上市辅导协议&#xff0c;计划登陆上交所主板。据了解这已经不是佳农食品第一次IPO了&#xff0c;2019 年&#xff0c;佳农集团曾向上交所递交过招股说明书&#xff0c;当时的招股书披露&#xff0c;佳农集团…

磁盘分区如何分? 电脑磁盘分区免费软件指南!

列出并比较顶级免费磁盘分区管理器软件&#xff0c;以选择适用于 Windows 的最佳分区软件&#xff1a; 系统分区在现代计算机设备中起着非常重要的作用。它们可以存储数据&#xff0c;使系统文件远离用户数据&#xff0c;并在同一台设备上安装多个操作系统。但是&#xff0c;这…

阿里云对象存储OSS怎么停止扣费

阿里云对象存储OSS一直扣费如何停止&#xff1f;如何关闭对象存储OSS&#xff1f;阿里云对象存储OSS没有关闭功能&#xff0c;如果不再使用对象存储OSS可以删除存储空间Bucket下的所有文件&#xff0c;详细说下阿里云对象存储OSS停止收费的方法&#xff1a; 阿里云对象存储OSS…

TS和JS的区别

1.TS和JS的区别 ts 是js的超集。 从执行环境上来看&#xff0c;浏览器、node.js 可以直接执行js,但不能执行ts;编译层面&#xff0c;Ts 有编译阶段&#xff0c;js 没有&#xff0c;只有转译阶段和lint阶段&#xff1b;ts更难写一点&#xff0c;但类型更安全。ts 代码写出来就是…

绿盾加密软件支持文件 CAD图纸加密 多平台Windows、Linux、Mac

绿盾加密软件支持文件CAD图纸加密&#xff0c;并且可以在多平台如Windows、Linux、Mac上运行。适用于各种商务服务、软件开发以及行业专用软件。 PC访问地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 绿盾加密软件的具体功能…

【三维重建】DreamGaussian:高斯splatting的单视图3D内容生成(原理+代码)

文章目录 摘要一、前言二、相关工作2.1 3D表示2.2 Text-to-3D2.3 Image-to-3D 三、本文方法3.1生成式 高斯 splitting3.2 高效的 mesh 提取3.3 UV空间的纹理优化 四. 实验4.1实施细节4.2 定性比较4.3 定量比较4.4 消融实验 总结&#xff08;特点、局限性&#xff09; 五、安装与…

C++ 中的模型预测路径积分 (MPPI) 控制

一、说明 模型预测路径积分控制&#xff08;MPPI&#xff09;是一种基于采样的模型预测控制算法。是MPC控制模型的延申和拓宽&#xff0c;要了解MPPI需要先理解MPC&#xff0c;参见文章&#xff1a;MPC预测控制概述和C 中的模型库-CSDN博客 二、模型预测路径积分 (MPPI) 控制 模…

如何破解压缩包密码,CTF压缩包处理

I. 引言 压缩包我们经常接触&#xff0c;用于对文件进行压缩存储/传输。压缩包处理在CTF比赛中是非常重要的一块&#xff0c;因为压缩包中可能包含重要信息&#xff1a;许多CTF题目会将关键信息隐藏在压缩包中&#xff0c;参赛者需要解压并查看其中的内容才能获取有用的线索。…

Day7力扣打卡

打卡记录 合法分组的最少组数&#xff08;贪心&#xff09; 链接 举例说明&#xff0c;假设 c n t [ x ] 32 cnt[x]32 cnt[x]32&#xff0c; k 10 k10 k10&#xff0c;那么 32 10 10 10 2 321010102 321010102&#xff0c;多出的 2 2 2 可以分成两个 1 1 1&#xf…

Html -- 文字时钟

Html – 文字时钟 文字时钟&#xff0c;之前在Android上实现了相关效果&#xff0c;闲来无事&#xff0c;弄个网页版的玩玩。。。直接上代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><titl…

SpringBoot+Vue实现AOP系统日志功能

AOP扫盲&#xff1a;Spring AOP (面向切面编程&#xff09;原理与代理模式—实例演示 logs表&#xff1a; CREATE TABLE logs (id int(11) NOT NULL AUTO_INCREMENT,operation varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 操作名称,type varchar(255) COLL…

鸿鹄工程项目管理系统 Spring Cloud+Spring Boot+Mybatis+Vue+ElementUI+前后端分离构建工程项目管理系统项目背景

鸿鹄工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离构建工程项目管理系统 1. 项目背景 一、随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性&#xff0c;公司对内部工程管…

uniapp canvas 无法获取 webgl context 的问题解决

uniapp canvas 无法获取 webgl context 的问题解决 一、问题描述 在 uniapp 中做一个查看监控视频的页面&#xff0c;用到的是 JSMpeg 这个库&#xff0c;原理就是前后台通过 websocket 不断推送新画面内容到前端&#xff0c;前端通过这个 JSMpeg 渲染到前端页面中指定的 can…

Vue2基础知识(五)插槽

&#x1f48c; 所属专栏&#xff1a;【Vue2】&#x1f600; 作 者&#xff1a;长安不及十里&#x1f4bb;工作&#xff1a;目前从事电力行业开发&#x1f308;目标&#xff1a;全栈开发&#x1f680; 个人简介&#xff1a;一个正在努力学技术的Java工程师&#xff0c;专注基础和…

如何打造小红书产品差异化,打造产品优势?

其实在当今的时代&#xff0c;我们实质上已经进入到了一个产能过剩的时代&#xff0c;这意味着大量的同质化产品出现在市场上&#xff0c;选择更多了但是选择也更少了。今天为大家分享下如何打造小红书产品差异化&#xff0c;打造产品优势&#xff1f; 下面是一些产品差异化策略…

动画系统的前世今生(一)

掐指一算&#xff0c;五年没更新过我的CSDN账号啦&#xff0c;方向也从人工智能变成了计算机图形学&#xff0c;当然也依旧会关注AI的发展&#xff0c;之前在知乎上写了一些文章[传送门]&#xff0c;后续也会逐渐同步到CSDN上&#xff5e; 这个系列将包含五篇文章&#xff0c;内…

栈和队列相关的OJ题

1.栈的压入、弹出序列 题目链接 栈的压入、弹出序列_牛客题霸_牛客网 (nowcoder.com) 题目描述 题目给出两个序列&#xff0c;一个是入序列pushV&#xff0c;一个是出序列popV&#xff0c;要求判断是否匹配入栈出栈的规则顺序。 解题思路 可以用数据模拟入栈出栈&#xf…

SpringBoot使用@Value获取不到yaml中配置的值

在最近的开发中遇到一个问题,使用Value获取yml文件中配置的属性时始终获取不到值,一开始我以为是没有注入的问题,或者没有写setter方法的问题,后来我发现这些都都写了然后开始百度发现获取不到属性值有这么几个原因 获取不到值的原因 1.没有使用Component注解,也就是没有注入…

技术文档工具『Writerside』抢鲜体验

前言 2023 年 10 月 16 日&#xff0c;JetBrains 宣布以早期访问状态推出 Writerside&#xff0c;基于 IntelliJ 平台的 JetBrains IDE&#xff0c;开发人员可使用它编写、构建、测试和发布技术文档&#xff0c;可以作为 JetBrains IDE 中的插件使用&#xff0c;也可以作为独立…

无论有没有按钮,iPhone都可以进行截屏操作!如何在iPhone上截屏

通过简单的按键组合&#xff0c;可以很容易地将iPhone屏幕的图片捕获到图像文件中&#xff0c;并保存到照片库中。以下是操作方法。 什么是屏幕截图 屏幕截图是指通常包含你在设备屏幕上看到的内容的精确副本的图像。在设备内拍摄的数字屏幕截图通常使用相机拍摄物理屏幕的照…