QTday05(TCP的服务端客户端通信)

实现聊天室功能

服务端代码:

pro文件需要导入  network

头文件:

#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();
public slots:void newConnectSlot();//建立连接的槽函数void readyReadSlot();//接收消息的槽函数private:Ui::Widget *ui;//实例化服务器对象QTcpServer *server;//创建存放客户端信息的容器QList<QTcpSocket *> socketList;
};
#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);}Widget::~Widget()
{delete ui;
}void Widget::on_startBtn_clicked()
{//监听任意ip的指定端口bool listen_res=server->listen(QHostAddress::Any,ui->portLine->text().toUInt());if(listen_res){//监听成功QMessageBox::information(this,"提示","设置监听成功",QMessageBox::Ok);}else{//监听失败QMessageBox::information(this,"提示","设置监听失败",QMessageBox::Ok);return;}//等待连接connect(server,&QTcpServer::newConnection,this,&Widget::newConnectSlot);
}void Widget::newConnectSlot()
{//接收到newConnect信号之后的槽函数,处理接下来的操作//获取客户端的套接字,加入容器QTcpSocket *s=server->nextPendingConnection();socketList.push_back(s);qDebug() << "有新客户连接" << s->peerName() << ";" << s->peerAddress().toString() << ":" << QString::number(s->peerPort()) <<endl;//此时如果客户端向服务器发送数据,客户端会发送一个readyRead信号connect(s,&QTcpSocket::readyRead,this,&Widget::readyReadSlot);
}void Widget::readyReadSlot()
{//客户端有数据发送,触发改槽函数//遍历容器,移除无效客户端,接收有效客户端消息for (int i=0;i<socketList.count();i++) {//如果是非链接状态就移除if(socketList.at(i)->state()==QAbstractSocket::UnconnectedState){socketList.removeAt(i);}}for (int i=0;i<socketList.count();i++) {//如果有字节,就读取并放到ui界面if(socketList.at(i)->bytesAvailable()){QByteArray msg=socketList.at(i)->readAll();QString msgInfo=socketList.at(i)->peerAddress().toString()+":"+QString::number(socketList.at(i)->peerPort())+":"+QString::fromLocal8Bit(msg);ui->listWidget->addItem(msgInfo);for (int j=0;j<socketList.count();j++) {socketList.at(j)->write(msg);}}}
}

ui:

客户端代码:

头文件

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QtDebug>
#include <QMessageBox>
#include <QTcpSocket>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_connnectBtn_clicked();void on_disconnectBtn_clicked();void on_sendBtn_clicked();public slots:void connnectedSlot();void readyReadSlot();void disconnectedSlot();private:Ui::Widget *ui;//实例化客户端QTcpSocket *socket;//定义全局变量存储用户名QString username;
};
#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->sendBtn->setDisabled(true);ui->disconnectBtn->setDisabled(true);ui->accoutLine->setText("张三");ui->ipLine->setText("192.168.125.77");ui->portLine->setText("8888");//连接成功会触发connected信号,只需要一次connect(socket,&QTcpSocket::connected,this,&Widget::connnectedSlot);//收信号connect(socket,&QTcpSocket::readyRead,this,&Widget::readyReadSlot);connect(socket,&QTcpSocket::disconnected,this,&Widget::disconnectedSlot);
}Widget::~Widget()
{delete ui;
}void Widget::on_connnectBtn_clicked()
{//连接服务器username=ui->accoutLine->text();QString ip=ui->ipLine->text();quint16 port=ui->portLine->text().toUInt();socket->connectToHost(ip,port);//判断是否连接成功:连接成功后,户端会自动发射一个connected信号,}void Widget::connnectedSlot()
{QMessageBox::information(this,"提示","连接成功");QString msg=username+"进入聊天室";socket->write(msg.toLocal8Bit());ui->sendBtn->setDisabled(false);ui->connnectBtn->setDisabled(true);ui->disconnectBtn->setDisabled(false);}void Widget::on_disconnectBtn_clicked()
{QString msg=username+"离开聊天室";socket->write(msg.toLocal8Bit());socket->disconnectFromHost();}void Widget::on_sendBtn_clicked()
{if(ui->infoLine->text().isEmpty()){QMessageBox::information(this,"提示","发送的消息不能为空");return;}QString msg=ui->infoLine->text();socket->write(msg.toLocal8Bit());ui->infoLine->setText("");
}
void Widget::readyReadSlot(){QByteArray msg=socket->readAll();ui->listWidget->addItem(QString::fromLocal8Bit(msg));
}void Widget::disconnectedSlot()
{ui->sendBtn->setDisabled(true);ui->disconnectBtn->setDisabled(true);ui->connnectBtn->setDisabled(false);QMessageBox::information(this,"提示","断开连接成功");
}

ui:

运行结果:客户端连接之后可以成功发送信息

今日思维导图:

将聊天功能加入到仿qq登录之后:

代码:

page2.h:

#ifndef PAGE2_H
#define PAGE2_H#include <QWidget>
#include <QMovie>
#include <QTcpSocket>
#include <QMessageBox>
#include <QDebug>
#define PORT 8888
#define IP "192.168.125.77"namespace Ui {
class Page2;
}class Page2 : public QWidget
{Q_OBJECTpublic:explicit Page2(QWidget *parent = nullptr);~Page2();
public slots:void login_slot();void connectedSlot();void readyReadSlot();
private slots:void on_sendBtn_clicked();private:Ui::Page2 *ui;QTcpSocket *socket;};#endif // PAGE2_H

widget.h:

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QMovie>
#include <QMessageBox>
#include <QDebug>
#include <QMouseEvent>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void mousePressEvent(QMouseEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;public slots:void loginButton_slot();signals:void login_signal();private:Ui::Widget *ui;QPoint p;//定义全局变量p,记录位置
public:static QString username;
};#endif // WIDGET_H

main.cpp:

#include "widget.h"
#include "page2.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();Page2 p2;QObject::connect(&w,&Widget::login_signal,&p2,&Page2::login_slot);return a.exec();
}

page2.cpp:

#include "page2.h"
#include "widget.h"
#include "ui_page2.h"Page2::Page2(QWidget *parent) :QWidget(parent),ui(new Ui::Page2)
{ui->setupUi(this);QMovie *movie = new QMovie(":/111/cai.gif");ui->label->setMovie(movie);ui->label->setScaledContents(true);movie->start();//实例化客户端socket=new QTcpSocket(this);qDebug() << "实例化客户端";//建立connected信号和指定槽函数的连接connect(socket,&QTcpSocket::connected,this,&Page2::connectedSlot);//建立readyRead信号和指定槽函数连接connect(socket,&QTcpSocket::readyRead,this,&Page2::readyReadSlot);}Page2::~Page2()
{delete ui;
}void Page2::login_slot()
{qDebug() << "登录按钮";this->show();//连接客户端socket->connectToHost(IP,PORT);
}void Page2::connectedSlot()
{//连接成功后触发该槽函数qDebug() << "连接成功";QMessageBox::information(this,"提示","连接成功");QString msg=Widget::username+"加入了聊天";socket->write(msg.toLocal8Bit());
}void Page2::readyReadSlot()
{//收到服务端发送的消息时触发该槽函数QByteArray msg=socket->readAll();ui->listWidget->addItem(QString::fromLocal8Bit(msg));
}void Page2::on_sendBtn_clicked()
{if(ui->infoEdit->toPlainText().isEmpty()){QMessageBox::information(this,"提示","发送的消息不能为空");return;}QString msg=ui->infoEdit->toPlainText();socket->write(msg.toLocal8Bit());ui->infoEdit->clear();
}

widget.cpp:

#include "widget.h"
#include "ui_widget.h"
QString Widget::username="";
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setFixedSize(560,430);this->setStyleSheet("background-color:#faf7ec");this->setWindowFlag(Qt::FramelessWindowHint);//无边框QMovie *movie = new QMovie(":/111/cai.gif");ui->backLabel->setMovie(movie);ui->backLabel->setScaledContents(true);movie->start();ui->closeButton->setStyleSheet("border-image:url(:/111/basketball.png)");ui->avatorLabel->resize(60,60);ui->avatorLabel->setStyleSheet("border-image:url(:/111/user.png);border-radius:30px");ui->accountLabel->setPixmap(QPixmap(":/111/account.jpg"));//ui->accountLabel->resize(40,40);ui->accountLabel->setScaledContents(true);ui->passwdLabel->setPixmap(QPixmap(":/111/passwd.jpg"));//ui->passwdLabel->resize(40,40);ui->passwdLabel->setScaledContents(true);ui->accoountLine->setPlaceholderText("账号");ui->passwdLine->setPlaceholderText("密码");ui->passwdLine->setEchoMode(QLineEdit::Password);ui->loginLabel->setPixmap(QPixmap(":/111/2.png"));ui->loginLabel->setScaledContents(true);ui->loginButton->setStyleSheet("background-color:#409EFF;border-radius:5px");connect(ui->closeButton,SIGNAL(clicked()),this,SLOT(close()));connect(ui->loginButton,&QPushButton::clicked,this,&Widget::loginButton_slot);}Widget::~Widget()
{delete ui;
}void Widget::loginButton_slot()
{//判断用户账号密码的正确性if(ui->accoountLine->text()=="admin"&&ui->passwdLine->text()=="123456"){username="admin";qDebug() << "登录成功" <<endl;QMessageBox::information(this,"提示","登录成功",QMessageBox::Ok);this->close();//开启新窗口,手动触发信号emit login_signal();}else{qDebug() << "账号或者密码错误" <<endl;int res=QMessageBox::information(this,"提示","账号或者密码错误,是否继续登录",QMessageBox::Ok|QMessageBox::No);if(res==QMessageBox::Ok){ui->passwdLine->setText("");}else{this->close();}}
}
void Widget::mousePressEvent(QMouseEvent *event){p=event->pos();
}
void Widget::mouseMoveEvent(QMouseEvent *event){if(event->buttons()==Qt::LeftButton)this->move(event->globalPos()-p);
}

page2.ui:

widget.ui:

运行结果:

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

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

相关文章

Adobe产品2024

一、软件下载&#xff1a; http://dt4.8tupian.net/2/29913a1b2000.pg3二、软件介绍&#xff1a; Adobe公司旗下的产品在影视后期、平面设计等领域有着无可取代的地位。在创意和设计领域中&#xff0c;产品有多达 21 个&#xff0c;包括 Photoshop、Illustrator、InDesign、P…

【软件教程】如何用C++交叉编译出能在Android运行的ELF程序或so动态库

一、配置NDK交叉编译平台 1. 打开Android的官方ndk下载链接https://developer.android.com/ndk/downloads?hlzh-cn&#xff0c;下载windows 64位ndk环境包。 2. 解压后将具有以下文件的路径加入到系统环境变量。 3. 配置好环境变量&#xff0c;如下图所示&#xff0c;Path中存…

使用GoogleNet网络实现花朵分类

一.数据集准备 新建一个项目文件夹GoogleNet&#xff0c;并在里面建立data_set文件夹用来保存数据集&#xff0c;在data_set文件夹下创建新文件夹"flower_data"&#xff0c;点击链接下载花分类数据集https://storage.googleapis.com/download.tensorflow.org/exampl…

推荐几个程序员必逛的个人技术博客网站

1、美团技术团队 地 址: 美团技术团队简 介&#xff1a;美团技术团队的博客&#xff0c;干货满满。推荐指数&#xff1a;⭐⭐⭐⭐⭐ ​ 2、阮一峰的网络日志 地 址: 阮一峰的个人网站 - Ruan YiFengs Personal Website简 介&#xff1a;大神阮一峰&#xff0c;博客风格真正…

PHP 在线考试管理系统mysql数据库web结构layUI布局apache计算机软件工程网页wamp

一、源码特点 PHP 在线考试管理系统是一套完善的web设计系统 layUI技术布局 &#xff0c;对理解php编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 PHP 在线考试系统1 代码 https://download.csdn.net/download/qq_41…

【31】c++设计模式——>模板方法模式

模板方法模式通常由以下几个部分组成&#xff1a; 1.抽象基类&#xff08;Abstract Base Class&#xff09;&#xff1a;抽象基类定义了一个算法的骨架&#xff0c;其中包含了模板方法和一些基本操作方法。模板方法在抽象基类中被声明为虚函数&#xff0c;它定义了算法的流程&…

制作macOS Ventura U盘启动盘教程

macOS 14更新一段时间了&#xff0c;发现某些应用不适配想要无损降级&#xff0c;如何进行macOS的降级呢&#xff0c;除了备份好的时间机器备份&#xff0c;还需要一个可以引导的macOS U盘安装器&#xff0c;如何制作macOS 13 Ventura 系统启动U盘呢&#xff0c;小编带来对新手…

线性表操作的实现--顺序表

本文参考朱战力老师的数据结构与算法--使用C语言一书 文章目录 前言 一、线性表是什么&#xff1f; 二、具体实现 1.顺序表的定义 2.初始化ListInitiate&#xff08;L&#xff09; 3.求当前元素个数ListLength&#xff08;L&#xff09; 4.插入元素ListInsert&#xff08;L&…

Ubuntu deadsnakes 源安装新版 python

前言 适用于 Ubuntu 安装 python3.11 等新版本。 因为比较常用并且不想重新编译就记录一下&#xff0c;方便以后面向CV安装。 安装 添加 deadsnakes ppa 源 sudo add-apt-repository ppa:deadsnakes/ppa更新 apt sudo apt update安装 python3.11 sudo apt install python…

电子元器件管理系统 JAVA语言开发

目录 一、系统介绍 二、系统下载 三、系统截图 一、系统介绍 基于VueSpringBootMySQL的电子元器件管理系统包含元器件单位模块、元器件仓库模块、元器供应商模块、元器件品类模块、元器件明细模块、元器件采购模块、元器件采购审核模块、元器件领用模块、学生元器件申请模块…

【华为路由器】配置企业通过5G链路接入Internet示例

场景介绍 5G Cellular接口是路由器用来实现5G技术的物理接口&#xff0c;它为用户提供了企业级的无线广域网接入服务&#xff0c;主要用于eMBB场景。与LTE相比&#xff0c;5G系统可以为企业用户提供更大带宽的无线广域接入服务。 路由器的5G功能&#xff0c;可以实现企业分支…

KNN(K近邻)水仙花的分类(含答案)

题目 以下采用K-NN算法来解决水仙花的分类问题&#xff0c;每个样本有两个特征&#xff0c;第一个为水仙花的花萼长度&#xff0c;第二个为水仙花 的花萼宽度&#xff0c;具体数据见表&#xff0c; 1&#xff09;设置k3&#xff0c; 采用欧式距离&#xff0c;分析分类精度为多少…

【Linux系统编程:信号】产生信号 | 阻塞信号 | 处理信号 | 可重入函数

写在前面 通过学习信号可以理解进程与进程的一个相对关系&#xff0c;还能理解操作系统与进程的关系。要注意的是进程间通信中的信号量与这里的信号没有半毛钱关系&#xff0c;就像老婆和老婆饼。 本文要点&#xff1a; 掌握 Linux 信号的基本概念掌握信号产生的一般方式理解…

树与二叉树(考研版)

文章目录 树与二叉树树的基本概念结点、树属性的描述树的性质 二叉树的概念二叉树的性质二叉树的构建二叉树的遍历先序遍历中序遍历后序遍历层次遍历 递归算法和非递归算法的转换源代码 线索二叉树二叉树的线索化线索二叉树 找前驱/后继 树和森林树的存储 树与二叉树的应用哈夫…

JavaScript快捷方式:15个简写技巧,让你的代码事半功倍!

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

依靠继承与聚合,实现maven搭建分布式项目

简介聚合 对于复杂的Maven项目&#xff0c;一般建议采用多模块的方式来设计开发&#xff0c;便于后期维护管理。但是构建项目时&#xff0c;如果每次都需要按模块一个一个进行构建会十分麻烦&#xff0c;而Maven的聚合功能就可以很好的解决这个问题&#xff0c;当用户对聚合模…

Ubuntu22.04安装,SSH无法连接

Ubuntu初始化安装后&#xff0c;系统默认不允许root通过ssh连接&#xff0c;因此需要完成三个设置 1.修改ssh配置文件 vim /etc/ssh/sshd_config 将PermitRootLogin注释打开&#xff0c;并将值改为yes 保存修改并退出 :wq 2.重启ssh服务 sudo service ssh restart 3.重新打…

UG\NX二次开发 设置视图中心 UF_VIEW_set_center

文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 感谢粉丝订阅 感谢 a1794902437 订阅本专栏,非常感谢。 简介 UG\NX二次开发 设置视图中心 UF_VIEW_set_center。如果视图NULL_TAG,则使用工作视图。 效果 代码 #include &qu…

Android12 启动页适配

印象中&#xff0c;在2022年末接到了一个针对Android12启动页适配的需求&#xff0c;当时也使用了一些适配方案&#xff0c;也写了一个Demo&#xff0c;但是最终没有付诸适配行动&#xff1b;当然并不是适配失败&#xff0c;而是根据官方适配方案适配后太丑了… 1024纪念文章&a…

SpringBoot整合Activiti7——任务监听器(七)

文章目录 一、任务监听器事件类型配置方式(选)代码实现xml文件创建监听器class方式expression方式delegateExpression 测试流程部署流程启动流程完成任务 一、任务监听器 任务监听器可以在任务创建、任务分配、任务完成、任务删除发生时触发&#xff0c;从而执行相应的逻辑。 事…