QT 与 C++实现基于[ TCP ]的聊天室界面

TCP客户端 

Widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpSocket>   //客户端类
#include <QMessageBox>
#include <QListWidgetItem>
#include <QDebug>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();public slots:void connected_slot();//connected信号对应槽函数的声明void readyRead_slot();void disconnected_slot();private slots:void on_connectbtn_clicked();void on_sendbtn_clicked();void on_disconnectbtn_clicked();private:Ui::Widget *ui;QString msgfor="";//实例化一个客户端指针QTcpSocket *socket;//定义一个变量存储用户名QString userName;
};
#endif // WIDGET_H

Widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <string>
#include<iostream>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget),socket(new QTcpSocket(this))//给客户端实例化空间
{ui->setupUi(this);//初始化界面,设置为不可用ui->msgEdit->setEnabled(false);ui->sendbtn->setEnabled(false);ui->disconnectbtn->setEnabled(false);//如果成功连接服务器,那么客户端就会自动发射一个connected()信号//将该信号连接到自定义的槽函数,书写逻辑代码。由于只需要连接一次,所以连接函数写在构造函数中connect(socket, &QTcpSocket::connected, this, &Widget::connected_slot);//此时说明客户端和服务器已经成功建立连接,如果服务器发来数据,那么客户端就会自动发射readyRead()信号//将该信号连接到自定义的槽函数中,读取数据。由于只需要连接一次,所以连接函数写在构造函数中connect(socket, &QTcpSocket::readyRead, this, &Widget::readyRead_slot);//如果成功与服务器断开连接,那么客户端就会自动发射disconnected信号//将信号连接到自定义的槽函数中处理逻辑代码 ,由于只需连接一次,所以连接函数写在构造函数中connect(socket, &QTcpSocket::disconnected, this, &Widget::disconnected_slot);
}Widget::~Widget()
{delete ui;
}
//connected信号对槽函数实现
void Widget::connected_slot()
{//连接成功QMessageBox::information(this,"","连接服务器成功");//告诉服务器 我来了userName = ui->userNameEdit->text();//组织语言QString msg = userName + ": 进入聊天室";//将信息发送给服务器socket->write(msg.toLocal8Bit());//此时说明客户端和服务器已经成功建立连接,如果服务器发来数据,那么客户端就会自动发射readyRead()信号//将该信号连接到自定义的槽函数中,读取数据。由于只需要连接一次,所以连接函数写在构造函数中ui->msgEdit->setEnabled(true); //设置可用ui->sendbtn->setEnabled(true);ui->disconnectbtn->setEnabled(true);ui->userNameEdit->setEnabled(false);//设置不可用ui->ipEdit->setEnabled(false);ui->portEdit->setEnabled(false);ui->connectbtn->setEnabled(false);
}//readyRead()信号对应槽函实现
void Widget::readyRead_slot()
{//读取服务器发来的数据QByteArray msg = socket->readAll();//将信息数据放入ui界面上QListWidgetItem *aItem;aItem=new QListWidgetItem();int num=userName.size();QString mmsg=QString::fromLocal8Bit(msg);//截取用户名QByteArray bytesSub = msg.left(num); // 截取字节QString mmsg1=QString::fromLocal8Bit(bytesSub);//判断用户名是否是自己if(mmsg1!=userName){aItem->setText(mmsg);ui->listWidget->addItem(aItem);}else{QString msg2=msgfor+":"+userName;aItem->setText(msg2);aItem->setTextAlignment(Qt::AlignRight);ui->listWidget->addItem(aItem);}
}//disconnected信号对应的槽函数实现
void Widget::disconnected_slot()
{ui->msgEdit->setEnabled(false); //设置不可用ui->sendbtn->setEnabled(false);ui->disconnectbtn->setEnabled(false);ui->userNameEdit->setEnabled(true);//设置可用ui->ipEdit->setEnabled(true);ui->portEdit->setEnabled(true);ui->connectbtn->setEnabled(true);
}//---连接服务器按钮对应的槽函数
void Widget::on_connectbtn_clicked()
{//获取ui界面上的ip 和 端口号QString ip = ui->ipEdit->text();quint16 port = ui->portEdit->text().toUInt(); //将字符串转换整型//让客户端连接服务器//函数原型:virtual void connectToHost(const QString &hostName, quint16 port, OpenMode mode = ReadWrite, NetworkLayerProtocol protocol = AnyIPProtocol);//参数一:服务器的ip地址//参数二:服务器的端口号socket->connectToHost(ip, port);//如果成功连接到服务器,客户端就会自动发射一个connected信号进行连接//我们就可以将该信号连接到自定义槽函数中处理逻辑代码,由于只需要连接一次//所以将连接函数写在构造函数中
}//发送按钮对应的槽函数处理
void Widget::on_sendbtn_clicked()
{//获取Ui界面上的内容QString msg = ui->msgEdit->text();msgfor=msg;msg = userName + ": " + msg;//将信息发送给服务器socket->write(msg.toLocal8Bit());//清空行编辑器ui->msgEdit->clear();
}//断开连接按钮 对应的槽函数
void Widget::on_disconnectbtn_clicked()
{//告诉服务 我走了QString msg = userName + ":  优雅的离开了聊天室";socket->write(msg.toLocal8Bit());//将客户端与服务器断开连接socket->disconnectFromHost();//如果成功与服务器断开连接,那么客户端就会自动发射disconnected信号//将信号连接到自定义的槽函数中处理逻辑代码 ,由于只需连接一次,所以连接函数写在构造函数中
}

TCP服务器

Widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpServer>   //服务器类
#include <QMessageBox>  //消息对话框类
#include <QDebug>
#include <QTcpSocket>   //客户端类
#include <QList>        //链表容器QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();public slots:void newConnect_slots();void readyRead_slot();private slots:void on_startbtn_clicked();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),server(new QTcpServer(this))//给服务器对象实例化具体的空间
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;
}//newConnect信号对应的槽函数
void Widget::newConnect_slots()
{//有新的用户连接qDebug() << "有新的用户连接...";//获取最新连接的客户端套接字//函数原型:virtual QTcpSocket *nextPendingConnection();QTcpSocket *s=server->nextPendingConnection();//将获取的客户端放入客户端容器中socketList.push_back(s);//程序运行至此,此时说明服务器和客户端已经建立了连接//如果有客户端向服务器发来数据,客户端就会自动发射一个readyRead信号//就可以将该信号连接到自定义的槽函数中,读取数据connect(s, &QTcpSocket::readyRead, this, &Widget::readyRead_slot);
}//readyRead信号对应的槽函数
void Widget::readyRead_slot()
{//遍历客户端容器,移除无效客户端for(int i=0; i<socketList.count(); i++){//判断客户端和服务器的连接状态//函数原型:SocketState state() const;//函数返回值 枚举值为0的表示未连接的if( socketList.at(i)->state() == 0){//删除该元素socketList.removeAt(i);}}//遍历客户端容器,寻找哪个客户端有数据待读for(int i=0; i<socketList.count(); i++){//函数功能:数据的字节//函数原型:qint64 bytesAvailable() const override;if( socketList.at(i)->bytesAvailable() != 0) //说明有数据{//读取客户端发来的数据QByteArray msg = socketList.at(i)->readAll();//将读取到的数据 放入ui界面上ui->listWidget->addItem(QString::fromLocal8Bit(msg));//将数据广播给所有客户端for(int j=0; j<socketList.count(); j++){socketList.at(j)->write(msg);}}}
}//启动服务器按钮对应的槽函数
void Widget::on_startbtn_clicked()
{//获取ui界面的端口号//将字符串转换成整形quint16 port=ui->portlineEdit->text().toUInt();//服务器设置监听//函数原型: bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);//参数1:监听的主机,可以是指定主机,也可以任意//参数2:监听的端口号,可以是指定,也可以系统提供//返回值:监听成功返回true  否则falseif(server->listen(QHostAddress::Any,port)){//监听成功QMessageBox::information(this,"","启动服务器成功!");}else{//监听失败QMessageBox::information(this,"","启动服务器失败!");return;}//此时服务器已经设置好监听,如果有客户端发来连接,那么服务器端就会自动发射一个newConnection()信号//将该信号连接到自定义的槽函数中,处理逻辑代码connect(server, &QTcpServer::newConnection, this, &Widget::newConnect_slots);
}

 思维导图

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

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

相关文章

SpingBoot集成kafka发送读取消息

SpingBoot集成kafka开发 kafka的几个常见概念 1、springboot和kafka对应版本&#xff08;重要&#xff09;2、创建springboot项目&#xff0c;引入kafka依赖2.1、生产者EventProducer2.2、消费者EventConsumer2.3、启动生产者的方法SpringBoot01KafkaBaseApplication2.4、appli…

map与set容器初识:初步运用map与set

前言&#xff1a; 本文主要讲解的时对于map与set容器的初步使用&#xff0c;希望大家对map与set容器不熟悉的看了之后可以快速运用set与map到日常中来。&#xff08;本文适合对vector等基础容器有一定基础的同学&#xff09; 一、set与map容器常见接口 迭代器接口与以往的所…

12 程序控制语句:循环控制(while、do-while、for、多重嵌套循环、死循环)

目录 1 while 循环 1.1 基本语法 1.2 流程图 1.3 计数循环 1.3.1 实现原则 1.3.2 案例&#xff1a;循环输出语句 1.3.3 案例&#xff1a;循环输出数字 7~15 1.3.4 案例&#xff1a;倒序输出数字 56 ~ 43 1.3.5 案例&#xff1a;输出 10&#xff08;包括 10&…

使用 Go 语言将 Base64 编码转换为 PDF 文件

使用Go语言将PDF文件转换为Base64编码-CSDN博客文章浏览阅读104次&#xff0c;点赞2次&#xff0c;收藏5次。本文介绍了如何使用 Go 语言将 PDF 文件转换为 Base64 编码&#xff0c;并保存到文件中。https://blog.csdn.net/qq_45519030/article/details/141224319 在现代编程中…

【WebSocket】websocket学习【二】

1.需求&#xff1a;通过websocket实现在线聊天室 2.流程分析 3.消息格式 客户端 --> 服务端 {"toName":"张三","message":"你好"}服务端 --> 客户端 系统消息格式&#xff1a;{"system":true,"fromName"…

SQL注入(head、报错、盲注)

目录 【学习目标、重难点知识】 【学习目标】 【重难点知识】 1. 报错注入 1.1 那么什么是报错注入呢&#xff1f; 1.2 报错注入原理 extractvalue函数 updatexml函数 1.3 靶场解析 靶场练习 2. HEAD注入 2.1 相关全局变量 2.2 靶场解析 burp暴力破解 靶场练习 3…

Spring核心思想讲解之控制反转(IOC)

控制反转概述 控制反转实现方式 XML方式 方式一 方式二 方式三 注解方式 第一步 第二步 第三步 依赖注入&#xff08;DI&#xff09;实现方式 XML方式 手动注入 set注入 构造器注入 自动注入 set注入 构造方法注入 注解方式 方式一&#xff1a; 方式二&…

Transformer模型中的Position Embedding实现

引言 在自然语言处理&#xff08;NLP&#xff09;中&#xff0c;Transformer模型自2017年提出以来&#xff0c;已成为许多任务的基础架构&#xff0c;包括机器翻译、文本摘要和问答系统等。Transformer模型的核心之一是其处理序列数据的能力&#xff0c;而Position Embedding在…

python之matplotlib (1 介绍及基本用法)

介绍 matplotlib是Python中的一个绘图库&#xff0c;它提供了一个类似于 MATLAB 的绘图系统。使用matplotlib你可以生成图表、直方图、功率谱、条形图、错误图、散点图等。matplotlib广泛用于数据可视化领域&#xff0c;是 Python 中最著名的绘图库之一。 同样matplotlib的安…

Java数组怎么转List,Stream的基本方法使用教程

Stream流 Java 的 Stream 流操作是一种简洁而强大的处理集合数据的方式,允许对数据进行高效的操作,如过滤、映射、排序和聚合。Stream API 于 Java 8 引入,极大地简化了对集合(如 List、Set)等数据的处理。 一、创建 Stream 从集合创建: List<String> list = Ar…

NGINX 之 location 匹配优先级

章节 1 NGINX 的源码安装 2 NGINX 核心配置详解 3 NGINX 之 location 匹配优先级 4 NGINX 基础参数与功能 目录 1 location 基础语法 1.1 location 语法说明表 1.2 URI部分简单介绍 2 location 匹配优先级 2.1 URI匹配的规则与顺序 2.2 精确匹配(location /1.txt) 2.3 区…

Python个人收入影响因素模型构建:回归、决策树、梯度提升、岭回归

全文链接&#xff1a;https://tecdat.cn/?p37423 原文出处&#xff1a;拓端数据部落公众号 “你的命运早在出生那一刻起便被决定了。”这样无力的话语&#xff0c;无数次在年轻人的脑海中回响&#xff0c;尤其是在那些因地域差异而面临教育资源匮乏的年轻人中更为普遍。在中国…

企业级WEB应用服务器——TOMCAT

一、WEB技术 1.1、HTTP协议和B/S 结构 最早出现了CGI&#xff08;Common Gateway Interface&#xff09;通用网关接口&#xff0c;通过浏览器中输入URL直接映射到一个 服务器端的脚本程序执行&#xff0c;这个脚本可以查询数据库并返回结果给浏览器端。这种将用户请求使用程…

AWS不同类型的EC2实例分别适合哪些场景?

Amazon Web Services&#xff08;AWS&#xff09;的弹性计算云&#xff08;EC2&#xff09;提供了多种实例类型&#xff0c;以满足不同的应用需求和工作负载。了解不同类型的 EC2 实例及其适用场景&#xff0c;可以帮助用户更好地优化性能和控制成本。九河云和大家一起了解一下…

安恒信息总裁宋端智,辞职了!活捉一枚新鲜出炉的餐饮人!

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》http://mp.weixin.qq.com/s?…

I/O模型

文章目录 I/O模型相关概念网络I/O模型阻塞型I/O模型非阻塞型I/O模型多路复用I/O型信号驱动式I/O型异步I/O模型 apache和nginx的区别&#xff0c;什么时候选择apache&#xff0c;什么时候选择nginx 文章相关连接如下&#xff1a; 如果想更多了解nginx&#xff0c;请点击&#x…

为什么要使用TikTok云手机

随着TikTok平台的日益繁荣&#xff0c;TikTok云手机作为一种新兴的运营工具&#xff0c;正以其独特的云端技术和用户体验&#xff0c;赢得广大用户的青睐。相较于传统手机&#xff0c;TikTok云手机通过云端技术为用户带来了一系列新的优势&#xff0c;让TikTok运营变得更加灵活…

涂料耐久性氙灯老化试验箱

涂料氙灯老化试验箱是现代检测手段中常用的一种设备&#xff0c;它能够模拟自然光照、光照老化等环境条件&#xff0c;对涂料、染料、塑料、橡胶、纺织品、涂层等材料进行老化试验&#xff0c;以评估其耐久性和使用寿命。本文将详细介绍涂料氙灯老化试验箱的工作原理、使用注意…

正则表达式——详解

正则表达式是什么&#xff1f; 正则表达式&#xff08;Regular Expression&#xff0c;通常简写为 regex、regexp 或 RE&#xff09;是一种强大的文本处理工具&#xff0c;用于描述一组字符串的模式。它可以用来匹配、查找、替换等操作&#xff0c;几乎所有现代编程语言都支持…

【流媒体】RTMPDump—RTMP_Connect函数(握手、网络连接)

目录 1. RTMP_Connect函数1.1 网络层连接&#xff08;RTMP_Connect0&#xff09;1.2 RTMP连接&#xff08;RTMP_Connect1&#xff09;1.2.1 握手&#xff08;HandShake&#xff09;1.2.2 RTMP的NetConnection&#xff08;SendConnectPacket&#xff09; 2.小结 RTMP协议相关&am…