tcp的聊天室

注意:要加库文件,服务端客户端都要加 network

客户端的头文件

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpSocket>//客户端类
#include <QMessageBox>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_sendbtn_clicked();void on_disconnectbtn_clicked();void on_connectbtn_clicked();
public slots:void connected_slot();void readyRead_slot();void disconnected_slot();private:Ui::Widget *ui;//定义客户端指针QTcpSocket *socket;//定义存储用户名QString username;
};
#endif // WIDGET_H

客户端主函数

#include "widget.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

 客户端构造函数

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//初始化界面//设置按钮不可以状态ui->msgEdit->setEnabled(false);ui->sendbtn->setEnabled(false);ui->disconnectbtn->setEnabled(false);//给客户端指针实例化空间socket=new QTcpSocket(this);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;
}//连接服务器按钮对应的槽函数处理
void Widget::on_connectbtn_clicked()
{//获取ui界面上的ip和端口号QString ip=ui->ipEdit->text();quint16 port =ui->portEdit->text().toUInt();//将客户连接到服务器//参数1:主机地址//参数2:端口号socket->connectToHost(ip,port);//如果成功连接服务器,那么客户端将发送一个conneted信号//我们就可以将该信号连接到自定义的槽函数中处理逻辑代码,由于只需要连接一次,所有我们在构造函数中写连接}void Widget::connected_slot()
{QMessageBox::information(this,"","连接服务器成!");//告诉服务器,用户上线username =ui->userEdit->text();QString msg=username+": 进入聊天室";//将信息发送给服务器socket->write(msg.toLocal8Bit());//将ui界面上的组件进行相关设置//可用状态ui->msgEdit->setEnabled(true);ui->sendbtn->setEnabled(true);ui->disconnectbtn->setEnabled(true);//不可以状态ui->userEdit->setEnabled(false);ui->ipEdit->setEnabled(false);ui->portEdit->setEnabled(false);ui->connectbtn->setEnabled(false);//此时客户端和服务器已经建立连接,如果服务器发来数据,那么客户端就会自动发射 一个readyRead()信号//我们可以将该信号连接到自定义的槽函数中,读取服务器端的数据,又由只需要连接一次,在构造函数写连接}void Widget::readyRead_slot()
{//将服务器端的数据读取出来QByteArray msg =socket->readAll();//将数据放入ui界面上ui->msgWidget->addItem(QString::fromLocal8Bit(msg));
}//disconnected信号对应的槽函数的实现
void Widget::disconnected_slot()
{QMessageBox::information(this,"","断开服务器成功");ui->msgEdit->setEnabled(false);ui->sendbtn->setEnabled(false);ui->disconnectbtn->setEnabled(false);ui->userEdit->setEnabled(true);ui->ipEdit->setEnabled(true);ui->portEdit->setEnabled(true);ui->connectbtn->setEnabled(true);}//发送按钮对应的槽函数
void Widget::on_sendbtn_clicked()
{//获取ui界面上的数据QString msg=ui->msgEdit->text();//整合信息msg=username+":"+msg;//将数据发送给服务器socket->write(msg.toLocal8Bit());//清空发送框里的内容ui->msgEdit->clear();
}//端口服务器按钮的槽函数处理
void Widget::on_disconnectbtn_clicked()
{//告诉大家我走了QString msg =username+":离开聊天室";//信息发送给服务器socket->disconnectFromHost();//如果成功与服务器断开连接,那么该客户端就会自动发送一个disconnected信号//我们就可以将该信号连接到自定义函数中,处理逻辑代码,由于只要连接一次,所有在构造函数中连接
}

客户端ui界面

 

服务端头文件

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpServer>
#include <QList> //链表容器
#include <QTcpSocket> //客户端的类
#include <QMessageBox> //消息对话框类QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_staetBtn_clicked();void newConnection_solt(); //newconnection信号对应的槽函数void readyRead_slot();private:Ui::Widget *ui;//定义服务器指针QTcpServer *server;//定义客户端容器QList<QTcpSocket *> socketList;};
#endif // WIDGET_H

服务端主函数

#include "widget.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

服务的构造函数

#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_staetBtn_clicked()
{//获取ui界面上的端口号quint16 port = ui->portEdit->text().toInt();//将服务器设置监听状态//函数原型:bool//参数1:主机地址 可以是任意//参数2:端口号if(server->listen(QHostAddress::Any,port)){QMessageBox::information(this,"","启动服务器成功!");}else{QMessageBox::information(this,"","启动服务器失败!");}//此时说明服务器已经进入监听状态,如果有客户端发来连接请求,那么服务器端就会自动发射newconnection//将该信号连接到自定义的槽函数中,获取客户端的套接字connect(server,&QTcpServer::newConnection,this,&Widget::newConnection_solt);
}//newConnection信号对应槽函数处理
void Widget::newConnection_solt()
{qDebug() <<"有新的用户连接" ;//获取最新连接的客户端套接字//函数原型:virtual QTcpSocket *nextPendingConnection();//返回值:是客户端套接字的指针QTcpSocket *s =server->nextPendingConnection();//将套接字放入容器中socketList.push_back(s);//程序运行至此,说明服务端和客户端已经建立起联系,如果客户端发来数据,那么客户端就会自动发射readyrRead()信号//我们就可以将信号连接自定义的槽函数中,读取客户端的数据connect(s,&QTcpSocket::readyRead,this,&Widget::readyRead_slot);}
//readyRead信号对应槽函数声明
void Widget::readyRead_slot()
{//移除无效客户端//count :在容器中的所有元素个数for(int i=0;i<socketList.count();i++){//函数原型:socketstate state() constif(socketList.at(i)->state()==0){//移除socketList.removeAt(i);//将下表为i的 客户端移除}}//遍历有效客户端,寻找哪个客户端有数据待读for (int i=0;i<socketList.count();i++){//函数原型://判断是否有数据if(socketList.at(i)->bytesAvailable()!=0){//读取套接字中的数据QByteArray msg = socketList.at(i)->readAll();//将数据放在ui界面上ui->msgWidget->addItem(QString::fromLocal8Bit(msg));//将数据广播给(发送)给所有客户端for(int j=0;j<socketList.count();j++){//将数据写入到套接字中socketList.at(j)->write(msg);}}}
}

服务端ui界面

 

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

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

相关文章

flutter调试器查看不了副页面(非主页面/子页面)

刚接触flutter&#xff0c;写了两个页面&#xff0c;通过按钮&#xff0c;可以从主页面跳转到副页面&#xff0c;副页面我自己写的一个独立的dart文件&#xff0c;在主页面的代码中导入使用。但是当我运行代码后&#xff0c;点击跳转的时候&#xff0c;却发现查看不到对应的副页…

​flutter 代码混淆

Flutter 应用混淆&#xff1a;Flutter 应用的混淆非常简单&#xff0c;只需要在构建 release 版应用时结合使用 --obfuscate 和 --split-debug-info 这两个参数即可。–obfuscate --split-debug-info 用来指定输出调试文件的位置&#xff0c;该命令会生成一个符号映射表。目前支…

Leetcode 139.单词拆分

OJ链接 &#xff1a;139.单词拆分 代码&#xff1a; class Solution {public boolean wordBreak(String s, List<String> wordDict) {Set<String> set new HashSet<String>(wordDict);int n s.length();boolean[] dp new boolean[n1];dp[0] true;//初始…

C# 编写Windows服务程序

1.什么是windows服务&#xff1f; Microsoft Windows 服务&#xff08;即&#xff0c;以前的 NT 服务&#xff09;使您能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序。这些服务可以在计算机启动时自动启动&#xff0c;可以暂停和重新启动而且不显示任何用…

Ajax原理以及优缺点

Ajax原理 1.Ajax的原理简单来说是在用户和服务器之间加了—个中间层(AJAX引擎)&#xff0c;通过XmlHttpRequest对象来向服务器发异步请求&#xff0c; 2.从服务器获得数据&#xff0c;然后用javascript来操作DOM而更新页面。使用户操作与服务器响应异步化。 3.这其中最关键的一…

jmeter配置使用(mac)

前言 这篇文件就是一个笔记&#xff0c;非mac用户不用看了&#xff0c;我这是换了mac&#xff0c;要用jmeter的倒腾。 一、下载 二、使用步骤 1.解压 tgz格式的直接用tar命令就行 tar -zxvf 包名2.启动 一种是进入解压包的bin目录启动 这种方式启动的就是命令框不能关闭&am…

UDP分片与丢包,UDP真的比TCP高效吗?

一、UDP 报文格式 每个 UDP 报文分为 UDP 报头和 UDP 数据区两部分。报头由 4 个 16 位长&#xff08;2 字节&#xff09;字段组成&#xff0c;分别说明该报文的源端口、目的端口、报文长度和校验值。 UDP 报文格式如图所示。 UDP 报文中每个字段的含义如下&#xff1a; 源端…

[LCTF 2018]bestphp‘s revenge

文章目录 前置知识call_user_func()函数session反序列化PHP原生类SoapClient 解题步骤 前置知识 call_user_func()函数 把第一个参数作为回调函数调用 eg:通过函数的方式回调 <?php function barber($type){echo "you wanted a $type haircut, no problem\n";}c…

【人工智能Ⅰ】实验8:DBSCAN聚类实验

实验8 DBSCAN聚类实验 一、实验目的 学习DBSCAN算法基本原理&#xff0c;掌握算法针对不同形式数据如何进行模型输入&#xff0c;并结合可视化工具对最终聚类结果开展分析。 二、实验内容 1&#xff1a;使用DBSCAN算法对iris数据集进行聚类算法应用。 2&#xff1a;使用DBS…

感知机(perceptron)

一、感知机 1、相关概念介绍 感知机&#xff08;perceptron&#xff09;是二分类的线性分类模型&#xff0c;属于监督学习算法。输入为实例的特征向量&#xff0c;输出为实例的类别&#xff08;取1和-1&#xff09;。 2、&#xff08;单层&#xff09;感知机存在的问题 感知机…

自动化测试、压力测试、持续集成

因为项目的原因&#xff0c;前段时间研究并使用了 SoapUI 测试工具进行自测开发的 api。下面将研究的成果展示给大家&#xff0c;希望对需要的人有所帮助。 SoapUI 是什么&#xff1f; SoapUI 是一个开源测试工具&#xff0c;通过 soap/http 来检查、调用、实现 Web Service …

【Jmeter】Jmeter基础5-Jmeter元件介绍之线程(用户)

2.5.1、线程组 一个线程组即一个虚拟用户组&#xff0c;线程组中的每个线程即为1个虚拟用户&#xff0c;每个线程互相隔离&#xff0c;互不影响参数说明&#xff1a; 在取样器错误后要执行的动作 继续&#xff1a;忽略错误&#xff0c;继续执行启动下一进程循环&#xff1a; 终…

【ARM Trace32(劳特巴赫) 使用介绍 6 -- 通用寄存器查看与修改】

请阅读【Trace32 ARM 专栏导读】 文章目录 通用寄存器查看与修改Rester 命令语法Register.InitRegister.RELOAD高亮显示Register变化的值多核寄存器显示设置寄存器的值修改 通用寄存器查看与修改 在使用Trace32进行调试时&#xff0c;有时候需要查看并修改通用寄存器、PC指针、…

Json数据报文解析-Gson库-JsonObject类-JsonParse类-JsonArray类

一、前言 本文我们将介绍如何解析Json数据&#xff0c;主要通过Gson库中的相关类来实现。 二、详细步骤 首先&#xff0c;我们要拿到一个基础的Json数据&#xff0c;这里将以下面的Json数据作为示例&#xff1a; {"code":"1","msg":"ok&q…

RFID复习内容整理

第一章 日常生活中的RFID技术 身份证&#xff08;高频&#xff09; typeB13.56MHz 一卡通&#xff08;高频&#xff09; ISO/IEC 14443 typeA 图书馆门禁停车场门票ETC 微波段、超高频 服装快销品牌 物联网定义 最初的定义 将各种信息传感设备&#xff0c;如射频识别(RFID)…

HarmonyOS(二)—— 初识ArkTS开发语言(下)之ArkTS声明式语法和组件化基础

前言&#xff1a; 通过前面ArkTS开发语言&#xff08;上&#xff09;之TypeScript入门以及ArkTS开发语言&#xff08;中&#xff09;之ArkTS的由来和演进俩文我们知道了ArkTS的由来以及演进&#xff0c;知道了ArkTS具备了声明式语法和组件化特性&#xff0c;今天&#xff0c;搭…

持续集成交付CICD:Jenkins使用GitLab共享库实现自动上传前后端项目Nexus制品

目录 一、实验 1.GitLab本地导入前后端项目 2.Jenkins新建前后端项目流水线 3.Sonarqube录入质量阈与质量配置 4.修改GitLab共享库代码 5.Jenkins手动构建前后端项目流水线 6.Nexus查看制品上传情况 7.优化代码获取RELEASE分支 8.优化Jenkins流水线项目名称 一、实验 …

Qt槽函数不响应不执行的一种原因:ui提升导致重名

背景&#xff1a; 一个包含了组件提升的ui&#xff0c;有个按钮的槽函数就是不响应&#xff0c;于是找原因。 分析&#xff1a; 槽函数的对应一是通过connect函数绑定信号&#xff0c;二是on_XXX_signal的命名方式。界面上部件的槽函数通常是第二种。 我反复确认细节&#…

CS144(2023 Spring)Lab 0:networking warmup(环境搭建 webget bytestream)

文章目录 前言其他笔记相关链接 1. Set up GNU/Linux on your computer2. Networking by hand3. Writing a network program using an OS stream socket3.1 Linux配置3.2 C规范3.3 Writing webget3.3.1 实现3.3.2 测试 4. An in-memory reliable byte stream4.1 思路分析4.2 代…

【技巧】导出和导入Typecho的文章数据

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 背景介绍 1、要换服务器了&#xff0c;虽然Typecho和Theme都可以重装&#xff0c;但文章数据由于是存在数据库里的&#xff0c;所以需要额外一些操作才行。 2、在进行下面的数据导入导出之前&#xff0c;新服务器…