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

基于Qt的UDP通信、TCP文件传输程序的设计与实现——QQ聊天群聊

🙌秋名山码民的主页
😂oi退役选手,Java、大数据、单片机、IoT均有所涉猎,热爱技术,技术无罪
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
获取源码,添加WX

目录

  • 前言
  • 一、主界面和聊天窗口
  • 二、UDP聊天
  • 三、TCP文件传输
    • server类
    • Clint类
  • 最后


前言

QQ是一款优秀的聊天软件,本文将提供主要代码和思路来实现一个类似于QQ群聊的网络聊天软件,大致有以下俩个功能:

采用qt5编写,实现基于UDP的文本聊天功能,和基于TCP的文件传输功能

基本聊天会话功能

通过获取每一个用户运行该程序的时候,发送广播来实现,不仅用户登录的时候进行广播,退出、发送信息的时候都使用UDP广播来告知用户,每个用户的聊天窗口为一个端点

文件传输功能实现

文件的传输采用TCP来实现,用C/S架构

  1. 主界面选中要发送的文件,单击传输,打开发送文件对话框
  2. 当用户单击发送的时候,程序通过UDP广播给接收端,接收端在收到文件的UDP消息后,弹出提示框,是否接收
  3. 如果接收,先创建一个TCP通信客户端,双方进行TCP通信,如果拒绝,再通过UDP广播告知发送端

一、主界面和聊天窗口

在这里插入图片描述

#ifndef DRAWER_H
#define DRAWER_H#include <QToolBox>
#include <QToolButton>
#include <QWidget>
#include "myqq.h"class Drawer : public QToolBox
{
public:Drawer();
private:QToolButton *toolBtn1;//聊天对象窗口指针QWidget *chatWidget1;private slots:// 显示聊天对象窗口void showChatWidget1();MyQQ *myqq;};#endif // DRAWER_H
 	setWindowTitle(tr("My QQ v01"));setWindowIcon(QPixmap(":/images/R-C.jpg"));toolBtn1 = new QToolButton;toolBtn1->setText(tr("冰雪奇缘"));toolBtn1->setIcon(QPixmap(":/images/girl1.jpg"));toolBtn1->setAutoRaise(true); //设置toolBtn1在显示时自动提升,使得按钮外观更加立体感。toolBtn1->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); //设置toolBtn1的按钮样式为图标在文本旁边的形式。// 将显示函数与抽屉盒中相对应的用户按钮进行绑定//connect(toolBtn1,SIGNAL(clicked()),this,SLOT(showChatWidget1()));//connect(toolBtn1, &QToolButton::clicked, this, &QToolBox::showChatWidget1);connect(toolBtn1, &QToolButton::clicked, this, &Drawer::showChatWidget1);

二、UDP聊天

原理:如果要进行聊天,则首先要获取所有登录用户的信息,这个功能是通过在每一个用户运行该程序时发送广播实现的,不仅用户登录时要进行广播,而且在用户退出、发送消息时都使用UDP广播来告知所有用户。

#ifndef SERVER_H
#define SERVER_H#include <QDialog>
#include <QFile>
#include <QTcpServer>
#include <QTime>namespace Ui {
class Server;
}class Server : public QDialog
{Q_OBJECTpublic:explicit Server(QWidget *parent = nullptr);~Server();void initSrv(); // 初始化服务器void refused(); // 关闭服务器protected:void closeEvent(QCloseEvent *);void updClntProgress(qint64 numBytes);private slots:void on_Server_accepted();void sendMsg(); //发送数据void updclntProgress(qint64 numBytes); // 更新进度条void on_sOpenBtn_clicked();void on_sSendBtn_clicked();void on_sCloseBtn_clicked();private:Ui::Server *ui;qint16 tPort;QTcpServer *tSrv;QString fileName;QString theFileName;QFile *locFile; //待发送的文件qint64 totalBytes; //总共要发送的qint64 bytesWritten; //已发送的qint64 bytesTobeWrite; //待发送的qint64 payloadSize;  //被初始化为一个常量QByteArray outBlock; // 缓存一次的QTcpSocket *clntConn;QTime time;signals:void sendFileName(QString fileName);
};#endif // SERVER_H
#include "server.h"
#include "ui_server.h"#include <QFile>
#include<QTcpServer>
#include<QTcpSocket>
#include<QMessageBox>
#include <QFileDialog>
#include<QDebug>Server::Server(QWidget *parent) :QDialog(parent),ui(new Ui::Server)
{ui->setupUi(this);setFixedSize(400,207);tPort = 5555;tSrv = new QTcpServer(this);connect(tSrv,&QTcpServer::newConnection,this,&Server::sendMsg);initSrv();
}void Server::initSrv()
{payloadSize = 64*1024;totalBytes = 0;bytesWritten = 0;ui->sOpenBtn->setEnabled(true);ui->sSendBtn->setEnabled(false);tSrv->close();
}// 发送数据
void Server::sendMsg()
{ui->sSendBtn->setEnabled(false);clntConn = tSrv->nextPendingConnection();connect(clntConn,SIGNAL(bytesWritten(gint64)),this,SLOT(updCIntProgress(qint64)));ui->sStatusLabel->setText(tr("开始传送文件 号1 !").arg(theFileName));locFile = new QFile(fileName);if(!locFile->open((QFile::ReadOnly))){QMessageBox::warning(this,tr("应用程序"), tr("无法读取文件号1: n各2").arg(fileName).arg(locFile->errorString()));return;}totalBytes = locFile->size();QDataStream sendOut(&outBlock, QIODevice::WriteOnly);sendOut.setVersion(QDataStream::Qt_4_7);time.start();QString curFile = fileName.right(fileName.size() - fileName.lastIndexOf('/') - 1);sendOut << qint64(0) << qint64((outBlock.size() - sizeof(qint64)*2));bytesTobeWrite = totalBytes - clntConn->write(outBlock);outBlock.reserve(0);
}// 更新进度条
void Server::updClntProgress(qint64 numBytes)
{// 防止传输大文件产生冻结qApp->processEvents();bytesWritten += (int)numBytes;if(bytesTobeWrite > 0){outBlock = locFile->read(qMin(bytesTobeWrite,payloadSize));bytesTobeWrite -= (int)clntConn->write(outBlock);outBlock.resize(0);} else{locFile->close();}ui->progressBar->setMaximum(totalBytes);ui->progressBar->setValue(bytesWritten);float useTime = time.elapsed();double speed = bytesWritten / useTime;ui->sStatusLabel->setText(tr("已发送 %1MB (%2MB/s)\n 共%3MB 已用时:%4s\n 估计剩余时间:%5秒").arg(bytesWritten/(1024*1024)).arg(bytesWritten / (1024*1024)).arg(speed*1000 / (1024*1024),0,'f',0).arg(totalBytes / (1024 * 1024)).arg(useTime/1000,0,'f',0).arg(totalBytes/speed/1000 - useTime/1000,0,'f',0));if(bytesWritten == totalBytes){locFile->close();tSrv->close();ui->sStatusLabel->setText(tr("传送文件 %1 成功").arg(theFileName));}}
Server::~Server()
{delete ui;
}void Server::on_sOpenBtn_clicked()
{fileName = QFileDialog::getOpenFileName(this);if(!fileName.isEmpty()){theFileName = fileName.right(fileName.size() - fileName.lastIndexOf('/')-1);ui->sStatusLabel->setText(tr("要发送的文件为:%1").arg(theFileName));ui->sOpenBtn->setEnabled(false);ui->sSendBtn->setEnabled(true);}
}void Server::on_sSendBtn_clicked()
{if(!tSrv->listen(QHostAddress::Any,tPort)){qDebug() << tSrv ->errorString();close();return;}ui->sStatusLabel->setText("等待……");emit sendFileName(theFileName);
}void Server::on_sCloseBtn_clicked()
{if(tSrv->isListening()){tSrv->close();if(locFile->isOpen())locFile->close();clntConn->abort();}close();
}void Server::closeEvent(QCloseEvent *)
{on_sCloseBtn_clicked();
}void Server::refused()
{tSrv->close();ui->sStatusLabel->setText(tr("对方拒绝!"));
}

三、TCP文件传输

文件的传输采用TCP来实现,用C/S(客户端/服务器)方式,创建俩个新类,client和server类

server类

在这里插入图片描述

#ifndef SERVER_H
#define SERVER_H#include <QDialog>
#include <QFile>
#include <QTcpServer>
#include <QTime>namespace Ui {
class Server;
}class Server : public QDialog
{Q_OBJECTpublic:explicit Server(QWidget *parent = nullptr);~Server();void initSrv(); // 初始化服务器void refused(); // 关闭服务器protected:void closeEvent(QCloseEvent *);void updClntProgress(qint64 numBytes);private slots:void on_Server_accepted();void sendMsg(); //发送数据void updclntProgress(qint64 numBytes); // 更新进度条void on_sOpenBtn_clicked();void on_sSendBtn_clicked();void on_sCloseBtn_clicked();private:Ui::Server *ui;qint16 tPort;QTcpServer *tSrv;QString fileName;QString theFileName;QFile *locFile; //待发送的文件qint64 totalBytes; //总共要发送的qint64 bytesWritten; //已发送的qint64 bytesTobeWrite; //待发送的qint64 payloadSize;  //被初始化为一个常量QByteArray outBlock; // 缓存一次的QTcpSocket *clntConn;QTime time;signals:void sendFileName(QString fileName);
};#endif // SERVER_H
#include "server.h"
#include "ui_server.h"#include <QFile>
#include<QTcpServer>
#include<QTcpSocket>
#include<QMessageBox>
#include <QFileDialog>
#include<QDebug>Server::Server(QWidget *parent) :QDialog(parent),ui(new Ui::Server)
{ui->setupUi(this);setFixedSize(400,207);tPort = 5555;tSrv = new QTcpServer(this);connect(tSrv,&QTcpServer::newConnection,this,&Server::sendMsg);initSrv();
}void Server::initSrv()
{payloadSize = 64*1024;totalBytes = 0;bytesWritten = 0;ui->sOpenBtn->setEnabled(true);ui->sSendBtn->setEnabled(false);tSrv->close();
}// 发送数据
void Server::sendMsg()
{ui->sSendBtn->setEnabled(false);clntConn = tSrv->nextPendingConnection();connect(clntConn,SIGNAL(bytesWritten(gint64)),this,SLOT(updCIntProgress(qint64)));ui->sStatusLabel->setText(tr("开始传送文件 号1 !").arg(theFileName));locFile = new QFile(fileName);if(!locFile->open((QFile::ReadOnly))){QMessageBox::warning(this,tr("应用程序"), tr("无法读取文件号1: n各2").arg(fileName).arg(locFile->errorString()));return;}totalBytes = locFile->size();QDataStream sendOut(&outBlock, QIODevice::WriteOnly);sendOut.setVersion(QDataStream::Qt_4_7);time.start();QString curFile = fileName.right(fileName.size() - fileName.lastIndexOf('/') - 1);sendOut << qint64(0) << qint64((outBlock.size() - sizeof(qint64)*2));bytesTobeWrite = totalBytes - clntConn->write(outBlock);outBlock.reserve(0);
}// 更新进度条
void Server::updClntProgress(qint64 numBytes)
{// 防止传输大文件产生冻结qApp->processEvents();bytesWritten += (int)numBytes;if(bytesTobeWrite > 0){outBlock = locFile->read(qMin(bytesTobeWrite,payloadSize));bytesTobeWrite -= (int)clntConn->write(outBlock);outBlock.resize(0);} else{locFile->close();}ui->progressBar->setMaximum(totalBytes);ui->progressBar->setValue(bytesWritten);float useTime = time.elapsed();double speed = bytesWritten / useTime;ui->sStatusLabel->setText(tr("已发送 %1MB (%2MB/s)\n 共%3MB 已用时:%4s\n 估计剩余时间:%5秒").arg(bytesWritten/(1024*1024)).arg(bytesWritten / (1024*1024)).arg(speed*1000 / (1024*1024),0,'f',0).arg(totalBytes / (1024 * 1024)).arg(useTime/1000,0,'f',0).arg(totalBytes/speed/1000 - useTime/1000,0,'f',0));if(bytesWritten == totalBytes){locFile->close();tSrv->close();ui->sStatusLabel->setText(tr("传送文件 %1 成功").arg(theFileName));}}
Server::~Server()
{delete ui;
}void Server::on_sOpenBtn_clicked()
{fileName = QFileDialog::getOpenFileName(this);if(!fileName.isEmpty()){theFileName = fileName.right(fileName.size() - fileName.lastIndexOf('/')-1);ui->sStatusLabel->setText(tr("要发送的文件为:%1").arg(theFileName));ui->sOpenBtn->setEnabled(false);ui->sSendBtn->setEnabled(true);}
}void Server::on_sSendBtn_clicked()
{if(!tSrv->listen(QHostAddress::Any,tPort)){qDebug() << tSrv ->errorString();close();return;}ui->sStatusLabel->setText("等待……");emit sendFileName(theFileName);
}void Server::on_sCloseBtn_clicked()
{if(tSrv->isListening()){tSrv->close();if(locFile->isOpen())locFile->close();clntConn->abort();}close();
}void Server::closeEvent(QCloseEvent *)
{on_sCloseBtn_clicked();
}void Server::refused()
{tSrv->close();ui->sStatusLabel->setText(tr("对方拒绝!"));
}

Clint类

TCP客户端类,用于接收文件。
在这里插入图片描述

#ifndef CLIENT_H
#define CLIENT_H#include <QDialog>
#include <QHostAddress>
#include <QFile>
#include <QTime>
#include <QTcpSocket>namespace Ui {
class client;
}class client : public QDialog
{Q_OBJECTpublic:explicit client(QWidget *parent = nullptr);~client();void setHostAddr(QHostAddress addr);void setFileName(QString name);protected:void closeEvent(QCloseEvent *);private:Ui::client *ui;QTcpSocket *tClnt;quint16 blockSize;QHostAddress hostAddr;qint16 tPort;qint64 totalBytes;qint64 bytesReceived;qint64 fileNameSize;QString fileName;QFile *locFile;QByteArray inBlock;QTime time;private slots:void newConn(); // 连接到服务器void readMsg(); // 读取文件数据
//    void displayErr(QAbstractSocket::SocketError); // 显示错误信息void on_cCancleBtn_clicked();void on_cCloseBtn_clicked();
};#endif // CLIENT_H
#include "client.h"
#include "ui_client.h"
#include <QDebug>
#include <QMessageBox>
#include <QTime>client::client(QWidget *parent) :QDialog(parent),ui(new Ui::client)
{ui->setupUi(this);setFixedSize(400,190);totalBytes = 0;bytesReceived = 0;fileNameSize = 0;tClnt = new QTcpSocket(this);tPort = 5555;connect(tClnt, &QTcpSocket::readyRead, this, &client::readMsg);}// 连接服务器
void client::newConn()
{blockSize = 0;tClnt->abort();tClnt->connectToHost(hostAddr,tPort);time.start();
}// 发送文件
void client::readMsg()
{QDataStream in(tClnt);in.setVersion(QDataStream::Qt_4_7);float useTime = time.elapsed();if (bytesReceived <= sizeof(qint64)*2){if ((tClnt->bytesAvailable() >= sizeof(qint64)*2) && (fileNameSize == 0)){in>>totalBytes>>fileNameSize;bytesReceived += sizeof(qint64)*2;}if((tClnt->bytesAvailable() >= fileNameSize) && (fileNameSize != 0)){in>>fileName;bytesReceived +=fileNameSize;if(!locFile->open(QFile::WriteOnly)){QMessageBox::warning(this,tr("应用程序"),tr("无法读取文件%1:\n%2.").arg(fileName).arg(locFile->errorString()));}return;}else{return;}}if (bytesReceived < totalBytes){bytesReceived += tClnt->bytesAvailable();inBlock = tClnt->readAll();locFile->write(inBlock);inBlock.resize(0);}ui->progressBar->setMaximum(totalBytes);ui->progressBar->setValue(bytesReceived);double speed = bytesReceived / useTime;ui->label_2->setText(tr("已接收 %1MB (%2MB/s)\n 共%3MB 已用时:%4s\n 估计剩余时间:%5秒").arg(bytesReceived/(1024*1024)).arg(speed*1000 / (1024*1024),0,'f',0).arg(totalBytes / (1024 * 1024)).arg(useTime/1000,0,'f',0).arg(totalBytes/speed/1000 - useTime/1000,0,'f',0));if(bytesReceived == totalBytes){locFile->close();tClnt->close();ui->label->setText(tr("接收文件 %1 成功").arg(fileName));}
}
client::~client()
{delete ui;
}void client::on_cCancleBtn_clicked()
{tClnt->abort();if(locFile->isOpen())locFile->close();}void client::on_cCloseBtn_clicked()
{tClnt->abort();if(locFile->isOpen())locFile->close();close();
}void client::closeEvent(QCloseEvent *)
{on_cCloseBtn_clicked();
}

最后

至此已完成,读者还可根据自己所需来添加一些拓展功能,更改字体、字号和颜色等等……如果本文对你有所帮助,还请三连支持一下博主!
请添加图片描述

相关文章:

基于Qt的UDP通信、TCP文件传输程序的设计与实现——QQ聊天群聊

&#x1f64c;秋名山码民的主页 &#x1f602;oi退役选手&#xff0c;Java、大数据、单片机、IoT均有所涉猎&#xff0c;热爱技术&#xff0c;技术无罪 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 获取源码&#xff0c;添加WX 目录 前言一…...

【C++】:STL中的string类的增删查改的底层模拟实现

本篇博客仅仅实现存储字符(串)的string 同时由于Cstring库设计的不合理&#xff0c;我仅实现一些最常见的增删查改接口 接下来给出的接口都是基于以下框架&#xff1a; private:char* _str;//思考如何不用constsize_t _size;size_t _capacity;//这样写可以const static size_t…...

【论文阅读笔记】Supervised Contrastive Learning

【论文阅读笔记】Supervised Contrastive Learning 摘要 自监督批次对比方法扩展到完全监督的环境中&#xff0c;以有效利用标签信息提出两种监督对比损失的可能版本 介绍 交叉熵损失函数的不足之处&#xff0c;对噪声标签的不鲁棒性和可能导致交叉的边际&#xff0c;降低了…...

数据库管理工具,你可以用Navicat,但我选DBeaver!

大家好&#xff0c;我是豆小匠。数据库GUI工具哪家强&#xff0c;众人遥指Navicat。 可是Navicat老贵了。 如果公司有正版授权的还好&#xff0c;如果没有正版授权&#xff0c;还不给你用盗版&#xff0c;那才叫绝绝子。 好了&#xff0c;主角登场&#xff0c;DBeaver&#x…...

数据库的三范式(Normalization)

数据库的三范式&#xff08;Normalization&#xff09;是关系数据库设计中的基本理论原则&#xff0c;旨在减少数据冗余和提高数据库的数据组织结构。三范式通过将数据分解为更小的表&#xff0c;并通过关系建立连接&#xff0c;使得数据库设计更加灵活、规范和容易维护。在这篇…...

【代码随想录】刷题笔记Day32

前言 实在不想做项目&#xff0c;周末和npy聊了就业的焦虑&#xff0c;今天多花点时间刷题&#xff01;刷刷刷刷&#xff01; 93. 复原 IP 地址 - 力扣&#xff08;LeetCode&#xff09; 分割startindex类似上一题&#xff0c;难点在于&#xff1a;判断子串合法性(0~255)、&…...

LeetCode算法题解(动态规划,背包问题)|LeetCode416. 分割等和子集

LeetCode416. 分割等和子集 题目链接&#xff1a;416. 分割等和子集 题目描述&#xff1a; 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 示例 1&#xff1a; 输入&#xff1a;nums [1,5,…...

Java Class 类文件格式看这一篇就够了

本文将揭开Java Class文件的神秘面纱&#xff0c;带你了解Class文件的内部结构&#xff0c;并从Class文件结构的视角告诉你&#xff1a; 为什么Java Class字节码文件可以“写一次&#xff0c;遍地跑”&#xff1f;为什么常量池的计数从1开始&#xff0c;而不是和java等绝大多数…...

『亚马逊云科技产品测评』活动征文|构建生态农场家禽系统

『亚马逊云科技产品测评』活动征文&#xff5c;构建生态农场家禽系统 授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道 前…...

[github配置] 远程访问仓库以及问题解决

作者&#xff1a;20岁爱吃必胜客&#xff08;坤制作人&#xff09;&#xff0c;近十年开发经验, 跨域学习者&#xff0c;目前于新西兰奥克兰大学攻读IT硕士学位。荣誉&#xff1a;阿里云博客专家认证、腾讯开发者社区优质创作者&#xff0c;在CTF省赛校赛多次取得好成绩。跨领域…...

mysql5.6 删除用户/ drop user

目录 前言查看用户删除用户删除没有用户名的用户 前言 CentOS5.6.51 MySQL Community Server (GPL)查看MySQL的版本 查看用户 mysql> select Host,User from user; ----------------------- | Host | User | ----------------------- | 10.0.101.112 | root …...

VMware三种网络模式

桥接模式 NAT(网络地址转换模式) Host-Only(仅主机模式) 参考&#xff1a; vmware虚拟机三种网络模式 - 知乎 (zhihu.com)...

Java虚拟机(JVM)的调优技巧和实战2

JVM是Java应用程序的运行环境&#xff0c;它负责管理Java应用程序的内存分配、垃圾收集等重要任务。在JVM的默认设置下&#xff0c;可能存在一些性能问题&#xff0c;因此需要进行调优。在本次分享中&#xff0c;作者将介绍一些实用的JVM实战调优技巧&#xff0c;以提高Java应用…...

2020年下半年试题一:论信息系统项目的成本管理

论文题目 1.概要叙述你参与过的信息系统项目&#xff08;项目的背景、项目规模、发起单位、目的、项目内容、组织结构、项目周期、交付的成果等&#xff09;&#xff0c;并说明你在其中承担的工作&#xff08;项目背景要求本人真实经历&#xff0c;不得抄袭及杜撰&#xff09;。…...

9. 回文数 --力扣 --JAVA

题目 给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 例如&#xff0c;121 是回文&#xff0…...

ChainLight zkSync Era漏洞揭秘

1. 引言 ChainLight研究人员于2023年9月15日&#xff0c;发现了zkSync Era主网的ZK电路的一个soundness bug&#xff0c;并于2023年9月17日&#xff0c;向Matter Labs团队报告了该问题。Matter Labs团队修复了该问题&#xff0c;并奖励了ChainLight团队5万USDC——为首个zkSync…...

01背包与完全背包学习总结

背包问题分类见下图 参考学习点击&#xff1a;代码随想录01背包讲解 01背包问题&#xff1a; 核心思路&#xff1a; 1、先遍历物品个数&#xff0c;再遍历背包容量。因为容量最先是最大的&#xff0c;往背包里放物品&#xff0c;所以背包容量在慢慢减少&#xff0c;但背包容量…...

基于单片机的公共场所马桶设计(论文+源码)

1.系统设计 本课题为公共场所的马桶设计&#xff0c;其整个系统架构如图2.1所示&#xff0c;其采用STC89C52单片机为核心控制器&#xff0c;结合HC-SR04人体检测模块&#xff0c;压力传感器&#xff0c;LCD1602液晶&#xff0c;蜂鸣器&#xff0c;L298驱动电路等构成整个系统&…...

注解案例:山寨Junit与山寨JPA

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 上篇讲了什么是注解&am…...

Codeforces Round 822 (Div. 2)(D前缀和+贪心加血量)

A.选三条相邻的边遍历一次求最小值 #include<bits/stdc.h> using namespace std; const int N 1e610,mod1e97; #define int long long int n,m; vector<int> g[N]; int a[N]; void solve() {cin>>n;int res2e18;for(int i1;i<n;i) cin>>a[i];sort…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

MySQL的pymysql操作

本章是MySQL的最后一章&#xff0c;MySQL到此完结&#xff0c;下一站Hadoop&#xff01;&#xff01;&#xff01; 这章很简单&#xff0c;完整代码在最后&#xff0c;详细讲解之前python课程里面也有&#xff0c;感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...

【若依】框架项目部署笔记

参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作&#xff1a; 压缩包下载&#xff1a;http://download.redis.io/releases 1. 上传压缩包&#xff0c;并进入压缩包所在目录&#xff0c;解压到目标…...