当前位置: 首页 > news >正文

【QT开发(14)】QT P2P chat 聊天

在【P2P学习(2)】P2P 通信,主要存在四种不同的网络模型的第一阶段:集中式P2P 模式

最简单的路由方式就是集中式,即存在一个中心节点保存了其他所有节点的索引信息,索引信息一般包括节点 IP 地址、端口、节点资源等。集中式路由的优点就是结构简单、实现容易。但缺点也很明显,由于中心节点需要存储所有节点的路由信息,当节点规模扩展时,就很容易出现性能瓶颈;而且也存在单点故障问题。

一般是有一个服务器,和一群客户端。各个客户端可以两两相互发送消息。各个客户端用IP地址和TCP/IP监听端口号进行标识。客户端,可执行注册和聊天过程;注册服务器,主要用于注册客户端和分发注册客户端信息。

技术点:

  • GUI
  • 多线程
  • 套接字编程

1 QT 项目引入库cmake

认识Qt5::Network
Qt中提供的所有的Socket类都是非阻塞的。

QTcpSocket 用于TCP/IP通信,作为客户端套接字使用。
QTcpServer 用于TCP/IP通信,作为服务器端套接字使用。
QUdpSocket 用于UDP通信,服务器,客户端均使用此套接字。

文档资料:

官方文档: Qt Network C++ Classes:https://doc.qt.io/qt-5/qtnetwork-module.html
C++ QTcpSocket::waitForConnected方法代码示例:https://vimsky.com/examples/detail/cpp-ex—QTcpSocket-waitForConnected-method.html

CMake下添加,在CMakelists.txt文件中添加以下代码

#设置Qt的支持
set(QT5_LIBRARIESQt5::Network)
#自动查找配置构建工程所需的程序库
find_package(Qt5Network REQUIRED)
#添加可执行文件所需要的库
target_link_libraries(${PROJECT_NAME} ${QT5_LIBRARIES} Qt5::Network)

然后,引入相关类的头文件:

#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>

2 TCP/IP协议

TCP/IP: TCP(Transmission Control Protocol,传输控制协议),IP(Internet Protocol 网络协议)。TCP提供一种机制可以让发送端根据接收端的实际接收能力控制发送的数据量,是一种流控制。认识TCP可通过以下方面。

  • TCP是一种面向连接的可靠的协议,属于传输层。只有在确认通信对端存在时才会发送数据,从而控制通信流量的浪费。
  • TCP特性: 既保证可靠性,又尽可能的提高性能。
    保证可靠性的机制: 校验和,序列号(按序到达),确认应答,超时重传,连接管理,流量控制,拥塞控制。
    提高性能的机制: 滑动窗口,快速重传,延迟应答,捎带应答。
    定时器: 超时重传定时器,保活定时器,TIME_WAIT定时器。
  • 基于 TCP 的应用层协议: HTTP,HTTPS,SSH,Telnet,FTP,SMTP,基于TCP的自定义的应用层协议。
  • TCP 和 UDP 对比: TCP用于可靠传输的情况, 应用于文件传输, 重要状态更新等场景。UDP用于对高速传输和实时性要求较高的通信领域,例如, 早期的QQ, 视频传输等.;UDP可以用于广播。

2.1 基础:Socket接口

Socket又称"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。

  • TCP/IP提供了封装或者显示数据的具体形式,即可供程序员做网络开发所用的接口。
    socket提供了网络通信的能力,其本质是对TCP/IP的封装的编程接口(API)。
    建立网络通信连接至少要一对Socket端口。
    TCP/IP如果是轿车的话,Socket就是发动机。

2.2 基础:QTcpServer

服务器监听客户端流程

1.创建套接字QTcpServer
2.监听指定的地址和端口号(周期性线程调用)
3.监听是否有Client连接
4.停止监听close
5.通过监听到的QTcpSocket收发数据
6.获取服务器监听状态

创建套接字

QTcpServer* server = new QTcpServer();

监听指定的地址和端口号,即进入Sever启动监听等待Client连接状态

bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);

监听是否有Client连接

QTcpSocket* QTcpServer::nextPendingConnection();

注意,返回的QTcpSocket只能再本线程使用;如果需要在别的线程管理该QTcpSocket,则需要重写QTcpServer::incomingConnection(),将QTcpSocket描述符传递给其他线程并再创建QTcpSocket。

void QTcpServer::incomingConnection(qintptr handle);

停止监听

void QTcpServer::close();

收发数据
根据第3不中返回的QTcpSocket指针,调用read()和write()接口。

其他辅助接口

获取己方和对方的IP和port

quint16 QTcpServer::serverPort() const;
QHostAddress QTcpServer::serverAddress() const;

获取服务器监听状态

bool QTcpServer::isListening() const;

ServerListen 断开重连机制

static int count = 0;
void UserServerlient::Listen() {//1.tcpServer的断开重连if (!tcpClient) { return; }if (isListening() != lastState) {count++;//服务器尝试重新监听某个地址和端口ServerListening();//判断当前服务器监听状态if (isListening()) {std::cout << localIP << "/" << localPort << " 断开重连count: " << count;count = 0;}}//数字10为断开重连次数,根据设置的线程周期时间和实际需求设置if (count >= 10) {lastState = false;delete this;count = 0;return;}//2.检测连接到的Clientif (!child_client) {child_client = server->nextPendingConnection(); //得到每个连进来的socketif (!child_client) {return;}}//检测到Client断开连接,清理内存if (child_client->state() == QAbstractSocket::UnconnectedState) {……}
}    

2.3 基础:QTcpSocket

客户端通信流程

1.创建套接字QTcpSocket
2.连接服务器,使用 QTcpSocket::connectToHost()
3.向服务器发送数据 QTcpSocket::write()
4.接收服务器数据 QTcpSocket::readAll()
5.断开Socket连接等接口
6.获取己方和对方的IP和port,Socket状态等;

创建套接字

QTcpSocket* socket = new QTcpSocket();

客户端连接到服务器端

// ### Qt6: de-virtualize connectToHost(QHostAddress) overload
void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, OpenMode mode = ReadWrite, NetworkLayerProtocol protocol = AnyIPProtocol);
void QAbstractSocket::connectToHost(const QHostAddress &address, quint16 port, OpenMode mode = ReadWrite);

连接成功或断开服务器端,或触发connected()和disconnected()信号

Q_SIGNALS:void QAbstractSocket::hostFound();void QAbstractSocket::connected();void QAbstractSocket::disconnected();void QAbstractSocket::stateChanged(QAbstractSocket::SocketState);

连接成功后发送数据。返回值:数据信息的长度。

qint64 QIODevice::write(const char *data, qint64 len);
qint64 QIODevice::write(const char *data);
qint64 QIODevice::write(const QByteArray &data);

连接成功接收数据。返回值:数据信息info

qint64 QIODevice::read(char *data, qint64 maxlen);
QByteArray QIODevice::read(qint64 maxlen);
QByteArray QIODevice::readAll();

当有新的数据到来时,会触发readyRead()信号。因此,要时刻检测数据有数据发送过来,此处应该放在一个循环中,如timer中。

Q_SIGNALS:void QIODevice::readyRead();void QIODevice::aboutToClose();

关闭TCP连接

//会等待数据被写完之后关闭套接字连接
void QAbstractSocket::disconnectFromHost();
//关闭套接字的I/O设备并调用disconnectFromHost()来关闭套接字的连接。
void QIODevice::close() override;     
//调用close(),终止当前连接并重置套接字。与disconnectFromHost()不同,这个函数会立即关闭套接字,丢弃写缓冲区中任何未处理的数据。     
void QAbstractSocket::abort(); 

其他辅助接口

获取己方和对方的IP和port

quint16 QAbstractSocket::localPort() const;
quint16 QAbstractSocket::peerPort() const;
QHostAddress QAbstractSocket::localAddress() const;
QHostAddress QAbstractSocket::peerAddress() const;
QString QAbstractSocket::peerName() const;

获取Socket状态

SocketState QAbstractSocket::state();
enum QAbstractSocket::SocketState {UnconnectedState,   //未连接状态ConnectedState,     //连接状态
};

ClientListen 断开重连机制

static int count = 0;
void UserSocketlient::Listen() {if (!tcpClient) { return; }if (CurrentSocketConnectState() != lastState) {count++;//客服端尝试连接服务器SocketConnecttoSever();//判断当前Socket连接状态if (CurrentSocketConnectState()) {std::cout << localIP << "/" << localPort << " 断开重连count: " << count;count = 0;}}//数字10为断开重连次数,根据设置的线程周期时间和实际需求设置if (count >= 10) {lastState = false;delete this;count = 0;return;}
}

3 开发P2P 的中心服务器

用途:
1、接受客户端的加盟,然后记录客户端的列表信息
2、分发列表信息的端口信息给全体客户端,这样客户端就可相互联系了,不需要中心服务器的支持。
3、实时更新列表,有些下线的,超时的用户踢出去,然后再次广播列表。

3.1 具体流程

参考了adomy/P2PChatRoom;
在这里插入图片描述

4 客户端

在这里插入图片描述

5打包程序

【QT开发(13)】QT发布到其他ubuntu用户

5.1 演示

在这里插入图片描述

仓库

https://gitee.com/hiyanyx/p2-pcha

参考

链接:https://blog.csdn.net/qq_43572400/article/details/128261772

相关文章:

【QT开发(14)】QT P2P chat 聊天

在【P2P学习&#xff08;2&#xff09;】P2P 通信&#xff0c;主要存在四种不同的网络模型的第一阶段&#xff1a;集中式P2P 模式 最简单的路由方式就是集中式&#xff0c;即存在一个中心节点保存了其他所有节点的索引信息&#xff0c;索引信息一般包括节点 IP 地址、端口、节…...

解决adb root命令时错误 adbd cannot run as root in production builds

我测试的手机是小米8&#xff0c;root权限已经刷过了&#xff0c;但是在pc端使用adb root命令的时候&#xff0c;会报错"adbd cannot run as root in production builds" 后来查资料发现是因为Magisk和安卓9版本的问题 https://www.cnblogs.com/jeason1997/p/124105…...

操作系统中套接字和设备独立性软件的关系

网络编程就是编写程序让两台联网的计算机相互交换数据。在我们不需要考虑物理连接的情况下&#xff0c;我们只需要考虑如何编写传输软件。操作系统提供了名为“套接字”&#xff0c;套接字是网络传输传输用的软件设备。 这是对软件设备的解释&#xff1a; 在操作系统中&#…...

C++ Qt/VTK装配体组成联动连接杆

效果 关键代码 #include "View3D.h" #include "Axis.h"#include <vtkActor.h> #include <vtkAppendPolyData.h > #include <vtkAreaPicker.h> #include <vtkAxesActor.h> #include <vtkBox.h> #include <vtkCamera.h>…...

File文件查找

用的是递归调用&#xff0c; &#xff08;递归死循环的结果是导致栈内存溢出错误&#xff09; 一.代码 package org.example;import java.io.File;public class day03 {public static void main(String[] args) {//文件查找&#xff0c;在d&#xff1a;temp下查找改名.mp4sea…...

小程序 wxml2canvas开发文档

wxml: <view class"share__canvas share__canvas1"><view class"share__canvas1-text draw_canvas" data-type"text" data-text"这是一段无边距文字">这是一段无边距文字</view> </view> <canvas canvas-…...

SpringCloud微服务 【实用篇】| 认识微服务

目录 一&#xff1a;认识微服务 1. 微服务框架介绍 2. 服务架构演变 3. 微服务技术对比 4. SpringCloud 图书推荐&#xff1a;《巧用ChatGPT快速提高职场晋升力》 一&#xff1a;认识微服务 本课程学习于黑马&#xff0c;会通过分层次学习&#xff0c;分为三部分去讲解微…...

Csdn文章编写参考案例

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…...

Jmeter性能测试:高并发分布式性能测试

​一、为什么要进行分布式性能测试 当进行高并发性能测试的时候&#xff0c;受限于Jmeter工具本身和电脑硬件的原因&#xff0c;无法满足我们对大并发性能测试的要求。 基于这种场景下&#xff0c;我们就需要采用分布式的方式来实现我们高并发的性能测试要求。 二、分布式性能…...

2015年亚太杯APMCM数学建模大赛B题城市公共交通服务水平动态评价模型求解全过程文档及程序

2015年亚太杯APMCM数学建模大赛 B题 城市公共交通服务水平动态评价模型 原题再现 城市公共交通服务评价是城市公共交通系统建设和提高公共交通运营效率的重要组成部分。对于公交企业&#xff0c;管理和规划部门&#xff0c;传统公交车站、线路和换乘枢纽的规划数据只是基于主…...

CCF CSP认证历年题目自练 Day40

题目 试题编号&#xff1a; 201412-3 试题名称&#xff1a; 集合竞价 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 256.0MB 问题描述&#xff1a; 问题描述   某股票交易所请你编写一个程序&#xff0c;根据开盘前客户提交的订单来确定某特定股票的开盘价和开盘成交量…...

闲聊一下写技术博客的一些感想

大家好&#xff0c;我是阿赵。   在我的163博客关闭之后&#xff0c;我就把一部分的博文移到了CSDN这边。不过实际上我有好几年都没有写过博客&#xff0c;所以这个博客的浏览量和粉丝数一直都不高。直到今年2023年的2月底开始&#xff0c;打算总结一下3DsMax的MaxScript的用…...

单片机为什么一直用C语言,不用其他编程语言?

单片机为什么一直用C语言&#xff0c;不用其他编程语言&#xff1f; 51 单片机规模小得拮据&#xff0c;C 的优势几乎看不到。放个类型信息进去都费劲&#xff0c;你还想用虚函数&#xff1f;还想模板展开&#xff1f;程序轻松破 10k。最近很多小伙伴找我&#xff0c;说想要一些…...

利用HTTP2,新型DDoS攻击峰值破纪录

亚马逊、Cloudflare 和谷歌周二联合发布消息称&#xff0c;一种依赖于 HTTP/2 快速重置技术的攻击行为对它们造成了破纪录的分布式拒绝服务 (DDoS) 攻击。 根据披露的信息&#xff0c;该攻击自8月下旬以来便一直存在&#xff0c;所利用的漏洞被跟踪为CVE-2023-44487&#xff0c…...

android鼠标滚轮事件监听方法

Overridepublic boolean onGenericMotionEvent(MotionEvent event) { //The input source is a pointing device associated with a display. //输入源为可显示的指针设备&#xff0c;如&#xff1a;mouse pointing device(鼠标指针),stylus pointing device(尖笔设备)if (0 ! …...

【C语言|关键字】C语言32个关键字详解(4)——其他(typedef、sizeof)

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…...

Hafnium简介和构建

安全之安全(security)博客目录导读 目录 一、Hafnium简介 二、Hafnium构建 2.1.1 先决条件 2.1.1.1 构建Host 2.1.1.2 工具链 2.1.1.3 依赖 2.1.1.4 获取源码 2.1.2 构建 一、Hafnium简介 可信固件为Armv8-A、Armv9-A和Armv8-M提供了安全软件的参考实现。它为SoC开发人…...

2023年香水行业数据分析:国人用香需求升级,高端香水高速增长

在人口结构变迁的背景下&#xff0c;“Z世代”作为当下我国的消费主力&#xff0c;正在将“悦己”消费推动成为新潮流。具备经济基础的“Z世代”倡导“高颜值”、“个性化”、“精致主义”&#xff0c;这和香水、香氛为代表的“嗅觉经济”的特性充分契合&#xff0c;因此&#…...

这可能是最简单的Page Object库

做过web自动化测试的同学&#xff0c;对Page object设计模式应该不陌生。 Page object库应该根据以下目标开发&#xff1a; Page object应该易于使用 清晰的结构 PageObjects 对于页面对象 PageModules对于页面内容 只写测试&#xff0c;而不是基础。 在可能的情况下防止…...

论文阅读——BERT

ArXiv&#xff1a;https://arxiv.org/abs/1810.04805 github&#xff1a;GitHub - google-research/bert: TensorFlow code and pre-trained models for BERT 一、模型及特点&#xff1a; 1、模型&#xff1a; 深层双向transformer encoder结构 BERT-BASE&#xff1a;(L12, H…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...