QT聊天室基于Tcp

 

server.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;
}//启动服务器按钮对应的槽函数
void Widget::on_startBtn_clicked()
{//获取ui界面上的端口号quint16 port = ui -> portEdit -> text().toUInt();//服务器设置监听//    bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);//    参数1:监听的地址,指定的主机,或任意//    参数2:监听的端口号,可以是指定,也可是系统提供bool ret = server -> listen(QHostAddress::Any, port);if(ret == false){QMessageBox::information(this, "", "启动服务器失败");return;}ui -> startBtn -> setText("已启动");//此时若有客户端发来连接请求,那么服务器就会自动发射一个newConnect()信号//我们就可以将该信号连接到自定义的槽函数中,获取客户端的套接字connect(server, &QTcpServer::newConnection, this, &Widget::new_connection_slot);}//有新的客户端连接 connect 对应的槽函数
void Widget::new_connection_slot()
{//连接最先连接的客户端套接字// 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++){if(socketList.at(i) -> state() == 0){//移除无效客户端socketList.removeAt(i);i--;}}//读取发来的数据for (int i = 0; i < socketList.count(); i++) {//判断客户端是否有数据待读//bytesAvailable();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++) {//不发送信息到发送信息的客户端if(i == j){continue;}socketList.at(j) -> write(msg);}}}
}

 sever.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket> //客户端的类
#include <QMessageBox>
#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 on_startBtn_clicked();void new_connection_slot();void readyRead_slot();private:Ui::Widget *ui;QTcpServer *server;//定义一个存放客户端的容器//template <typename T>//class QListQList<QTcpSocket *> socketList;
};
#endif // WIDGET_H

 client.cpp

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget),socket(new QTcpSocket(this))       //给客户端实例空间 ,指定父对象this
{ui->setupUi(this);//初始化界面ui -> usrEdit -> setText("风呤");ui -> portEdit -> setText("8888");ui -> ipEdit -> setText("192.168.127.22");ui -> msgEdit -> setEnabled(false);ui -> sendbtn -> setEnabled(false);ui -> disLinkEdit -> setEnabled(false);
//    ui -> listWidget -> setMaxLength();//设置文本自动换行ui -> listWidget -> setWordWrap(true);connect(socket, &QTcpSocket::connected, this, &Widget::connected_slot);connect(socket, &QTcpSocket::disconnected, this, &Widget::disconnect_slot);}Widget::~Widget()
{delete ui;
}//连接服务器按钮对应的槽函数
void Widget::on_linkBtn_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);socket -> connectToHost(ip, port);//若成功连接服务器,那么客户端就会发送一个connected()信号//那么我们就可以将该信号连接到自定义的槽函数中处理逻辑代码,由于只需连接一次,故连接函数可写入构造函数中connect(socket, &QTcpSocket::readyRead, this, &Widget::readyRead_slot);
}void Widget::connected_slot()
{//告诉服务器我来了usrname = ui -> usrEdit -> text();QString msg = usrname + ":已进入聊天室";//将信息发送到服务器socket  -> write(msg.toLocal8Bit());//连接服务器成功QMessageBox::information(this, "", "已连接");//组件可用的相关设置ui -> msgEdit -> setEnabled(true);ui -> sendbtn -> setEnabled(true);ui -> disLinkEdit -> setEnabled(true);ui -> ipEdit -> setEnabled(false);ui -> linkBtn -> setEnabled(false);ui -> portEdit -> setEnabled(false);ui -> usrEdit -> setEnabled(false);//程序运行到此,说明客户端成功与服务器建立连接,若服务器发来数据,那么客户端就会自动发射一个readyRead信号//我们就可以将该信号连接到自定义的槽函数,读取数据,
}void Widget::disconnect_slot()
{ui -> msgEdit -> setEnabled(false);ui -> sendbtn -> setEnabled(false);ui -> disLinkEdit -> setEnabled(false);ui -> ipEdit -> setEnabled(true);ui -> linkBtn -> setEnabled(true);ui -> portEdit -> setEnabled(true);ui -> usrEdit -> setEnabled(true);
}void Widget::readyRead_slot(){//QByteArray msg = socket -> readAll();//ui -> listWidget -> addItem(QString::fromLocal8Bit(msg));}//发送按钮对应的槽函数
void Widget::on_sendbtn_clicked()
{//获取ui界面上的信息QString msg = ui -> msgEdit -> text();QString msg1 = msg + ":" + usrname;msg = usrname +  ":" + msg;//发送给服务器socket -> write(msg.toLocal8Bit());//将发送的文本输出到listWidget中QListWidgetItem * item= new QListWidgetItem(msg1);ui-> listWidget -> addItem(item);item->setTextAlignment(Qt::AlignRight);//右对齐//清空行编辑器ui -> msgEdit -> clear();
}void Widget::on_disLinkEdit_clicked()
{//告诉服务器断开连接QString msg = usrname + ":已离开";socket -> write(msg.toLocal8Bit());socket -> disconnectFromHost();//若成功断开,那么客户端就会发送一个disconnected信号//我们就可以将该信号连接到自定义的槽函数}

 client.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpSocket>
#include <QMessageBox>
#include <QLineEdit>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_linkBtn_clicked();void connected_slot();void disconnect_slot();void readyRead_slot();void on_sendbtn_clicked();void on_disLinkEdit_clicked();private:Ui::Widget *ui;QTcpSocket *socket;QString usrname;
};
#endif // WIDGET_H

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

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

相关文章

LLVM - 编译器后端-指令选择

一:概述 任何后端的核心都是指令选择。LLVM 实现了几种方法;在本篇文章中,我们将通过选择有向无环图(DAG)和全局指令选择来实现指令选择。 在本篇文章中,我们将学习以下主题: • 定义调用约定规则:本节展示如何在目标描述中设置调用约定的规则。 • 通过选择 D…

音频采集spring_ws_webrtc (html采集麦克风转gb711并发送广播播放)完整案例

下载地址&#xff1a;http://www.gxcode.top/code 项目说明 springbootwebscoektwebrtc 项目通过前端webrtc采集麦克风声音&#xff0c;通过websocket发送后台&#xff0c;然后处理成g711-alaw字节数据发生给广播UDP并播放。 后台处理项目使用线程池(5个线程)接受webrtc数据并…

mac如何恢复被同名替换掉的文件夹 mac文件被替换如何恢复

Mac系统一直以高性能遥遥领先其他的Windows系统&#xff0c;因此&#xff0c;Mac虽然价格远远高出其他的笔记本电脑&#xff0c;但是还是受到了一众用户的青睐。使用mac时&#xff0c;我们也经常会将一个文件命名为已经有了相同文件的文件名&#xff0c;且保存到同一个目标地址…

SQL - 内置函数

处理数值数据的函数 round(3.555,2) //四舍五入&#xff0c;第二个参数为精度值&#xff0c;为3.56 truncate(3.999,2) //用来截断数字&#xff0c;第二个参数为保留位数&#xff0c;为3.99 ceiling(7.1) //上限函数&#xff0c;返回不小于数字的最小整数&#xff0c;为8 foolr…

MATLAB-PSO-BiTCN-BiLSTM-Attention多变量分类

一、数据集 数据特征&#xff1a;12个多分类&#xff1a;4分类 ​ 二、PSO-BiTCN-BiLSTM-Attention网络 PSO-BiTCN-BiLSTM-Attention 网络是一种结合了多种深度学习技术和优化算法的复杂模型&#xff0c;用于处理时序数据任务&#xff0c;如时间序列预测、分类或其他相关问题…

白骑士的HTML教学实战项目篇 4.1 创建个人网站

创建个人网站不仅是展示自己作品、技能和兴趣的理想方式&#xff0c;也是实践HTML、CSS、JavaScript等前端技术的绝佳机会。在本篇博客中&#xff0c;我们将带你一步步构建一个功能齐全、视觉美观的个人网站。从最初的网站规划与设计&#xff0c;到实现页面导航与布局&#xff…

【Linux】——进程概念(万字解读)

一 冯诺依曼体系结构 在此之前&#xff0c;我们先要理解我们计算机的冯诺依曼体系结构&#xff0c;因为是进程的基础 我们所有的操作其实都是基于这样一个模型&#xff0c;比如你在qq上&#xff0c;和别人发送消息&#xff0c;这个消息肯定是先通过输入设备进行输入&#xf…

一个注解轻松搞定审计日志服务!

【审计日志】&#xff0c;简单的说就是系统需要记录谁&#xff0c;在什么时间&#xff0c;对什么数据&#xff0c;做了什么样的更改&#xff01;任何一个 IT 系统&#xff0c;如果要过审&#xff0c;这项任务基本上也是必审项&#xff01; 实现【审计日志】这个需求&#xff0…

整体思想以及取模

前言&#xff1a;一开始由于失误&#xff0c;误以为分数相加取模不能&#xff0c;但是其实是可以取模的 这个题目如果按照一般方法&#xff0c;到达每个节点再进行概率统计&#xff0c;但是不知道为什么只过了百分之十五的测试集 题目地址 附上没过关的代码 #include<bits…

Vue3知识干货分享

在 Vue 3 中&#xff0c;setup 函数的写法有两种主要方式&#xff1a;一种是使用 <script setup> 标签&#xff0c;另一种是写在 export default 对象中作为 setup 函数。它们之间的区别如下&#xff1a; <script setup> 标签 位置&#xff1a;使用 <script set…

联想闪电鲨移动硬盘文件没删除却消失了怎么办

在日常的数据存储与管理中&#xff0c;移动硬盘作为便携且容量可观的存储设备&#xff0c;深受用户青睐。然而&#xff0c;当您发现联想闪电鲨移动硬盘中的文件突然消失&#xff0c;而您确信并未进行删除操作时&#xff0c;这无疑会令人感到困惑与焦虑。本文旨在为您揭开这一谜…

vue-element-admin——<keep-alive>不符合预期缓存的原因

vue-element-admin——<keep-alive>不符合预期缓存的原因 本文章&#xff0c;以现在中后台开发用的非常多的开源项目vue-element-admin为案例。首先&#xff0c;列出官方文档与缓存<keep-alive>相关的链接&#xff08;请认真阅读&#xff0c;出现缓存<keep-ali…

在IEDA里打包Maven项目记录

之前在网上查找到的方式发现比较繁琐&#xff0c;所以把自己的解决办法记录一下分享给兄弟们 <plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.2.4</vers…

集合及数据结构第一节————初识集合框架和数据结构

系列文章目录 集合及数据结构第一节————初识集合框架和数据结构 初始集合框架和数据结构 什么是集合框架&#xff1f;集合框架的重要性背后所涉及的数据结构以及算法数据结构的基本概念和术语逻辑结构和物理结构数据类型 文章目录 系列文章目录集合及数据结构第一节——…

文件的读写(标准库函数与系统调用函数),文件描述符的复制

文件描述符 为了解决内核对象在可访问性与安全”性之间的矛盾&#xff0c;Unix系统通过所谓的文件描述符&#xff0c;将位于内核空间中的文件表项间接地提供给运行于用户空间中的程序代码。为了便于管理在系统中运行的各个进程&#xff0c;内核会维护一张存有各进程信息的列表&…

浮点数计算

看这么一小段内容&#xff1a; Test public void testDouble() {double a 0.0000010;double b 10.0;log.info("a * b {}", a * b); } 想要的是通过计算a*b后获取到的值应该是0.00001&#xff0c;但是实际上算出来的值是&#xff1a; a * b 9.999999999999999E…

C++智能指针配合STL模板类

代码 #include <unordered_map> #include <set> #include <memory> class ResID { public:using SP std::shared_ptr<ResID>;ResID() default;ResID(const std::string& id, const std::string& type): m_id(id), m_type(type){}public:~Re…

HoloLens 坐标系统 Coordinate systems

Hololens 和 Unity 空间坐标系统-CSDN博客文章浏览阅读79次。这意味着&#xff0c;在 X、Y 或 Z 轴上相距 2 个单位的物体&#xff0c;在混合现实中的渲染效果是相距 2 米。虽然左手坐标和右手坐标是最常见的系统&#xff0c;但 3D 软件中也会使用其他坐标系。例如&#xff0c;…

Veritas NBU8.3.0.2 安装部署环境备份实施介绍(篇一)

1、本次有两台NBU服务器&#xff0c;都是Windows Server 2016 Standard 2、一台作为Master Server角色&#xff0c;另外一台则作为Media Server角色 3、两台服务器均已加入域并关闭防火墙 4、后期备份客户端会有Linux和Windows系统&#xff0c;也会对接VCenter无代理备份虚拟…

springboot controller参数中如何传递字符串数组

在Spring Boot的Controller中&#xff0c;接收字符串数组作为参数可以通过以下几种方式实现&#xff0c;取决于传递数组的方式&#xff08;比如通过请求参数、路径变量、或者请求体&#xff09;。以下是常见的方法&#xff1a; 1. 通过请求参数传递字符串数组 你可以通过Requ…