当前位置: 首页 > 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…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...