QT TCP网络通信编程

学习目标: TCP网络通信编程

前置环境

运行环境:qt creator 4.12

学习内容

一、TCP 协议基础知识:

  1. TCP 是一种面向连接的、可靠的、基于字节流的传输层通信协议。
  2. TCP 拥塞控制算法包括慢启动、拥塞避免、快速重传和快速恢复。
  3. TCP 通信需要建立连接,Qt 提供 QTcpSocket 和 QTcpServer 类用于 TCP 客户端和服务器编程。
  4. QTcpServer 类用于建立网络监听和 socket 连接,主要接口函数如 listen()、newConnection() 等。

QTcpServer* tcpServer; 它负责监听指定的 IP 地址和端口,并在有新的客户端连接时发出 newConnection() 信号。

QTcpSocket* tcpSocket; 它代表一个与服务端建立的 TCP 连接。

QTcpServer类

QTcpServer 是 Qt 框架提供的 TCP 服务器类,它提供了一系列常用的成员函数和信号,用于实现 TCP 服务器的基本功能。以下是 QTcpServer 的一些常用成员函数:

  1. 构造函数和析构函数:

    • QTcpServer(QObject *parent = nullptr):创建一个 QTcpServer 对象。
    • ~QTcpServer():析构函数,用于释放资源。
  2. 服务器状态控制:

    • bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0):开始监听指定的地址和端口。
    • void close():停止监听并关闭服务器。
    • bool isListening() const:检查服务器是否正在监听。
  3. 获取服务器信息:

    • QHostAddress serverAddress() const:返回服务器绑定的地址。
    • quint16 serverPort() const:返回服务器绑定的端口。
    • QAbstractSocket::SocketError socketError() const:返回最近一次发生的套接字错误。
    • QString errorString() const:返回最近一次发生的错误的描述字符串。
  4. 新连接管理:

    • QTcpSocket *nextPendingConnection():返回下一个待处理的连接。
    • int hasPendingConnections() const:返回待处理连接的数量。
  5. 信号处理:

    • void newConnection():当有新的连接到达时发出此信号。
    • void acceptError(QAbstractSocket::SocketError socketError):当接受新连接时发生错误时发出此信号。
  6. 其他功能:

    • void setMaxPendingConnections(int numConnections):设置服务器可以同时处理的最大待处理连接数。
    • int maxPendingConnections() const:返回服务器的最大待处理连接数。
    • void setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value):设置套接字选项。
    • QVariant socketOption(QAbstractSocket::SocketOption option) const:获取套接字选项的当前值。
  7. 地址和端口设置:

    • void setAddress(const QHostAddress &address):设置服务器监听的地址。
    • QHostAddress address() const:返回服务器监听的地址。
    • void setPort(quint16 port):设置服务器监听的端口。
    • quint16 port() const:返回服务器监听的端口。
  8. SSL/TLS 支持:

    • void setSecureMode(QSsl::SslMode mode):设置服务器的 SSL/TLS 模式。
    • QSsl::SslMode secureMode() const:返回服务器的 SSL/TLS 模式。
    • void setLocalCertificate(const QSslCertificate &certificate):设置服务器的本地证书。
    • QSslCertificate localCertificate() const:返回服务器的本地证书。
    • void setPrivateKey(const QSslKey &key):设置服务器的私钥。
    • QSslKey privateKey() const:返回服务器的私钥。
  9. 线程安全:

    • void setThreadPool(QThreadPool *threadPool):设置用于处理新连接的线程池。
    • QThreadPool *threadPool() const:返回用于处理新连接的线程池。
  10. 日志记录:

    • void setProxy(const QNetworkProxy &proxy):设置代理服务器。
    • QNetworkProxy proxy() const:返回当前使用的代理服务器。

这些成员函数提供了更多的灵活性和控制能力,使开发者能够根据具体需求配置和管理 TCP 服务器。例如,可以设置 SSL/TLS 模式以提供安全的通信,使用线程池来提高并发处理能力,以及设置代理服务器以实现更复杂的网络拓扑。

QTcpServer 类的使用:

  • QTcpServer 是从 QObject 继承的类,用于服务器建立网络监听和创建网络 socket 连接。
  • 主要接口函数包括 listen()nextPendingConnection()serverAddress() 和 serverPort() 等。

服务器Server提供的回调函数

在 Qt TCP 编程中,主要提供了以下几种重要的回调接口:

  1. QTcpServer 相关的回调:

    • QTcpServer::newConnection(): 当有新的客户端连接到达时触发该信号。
    • QTcpServer::acceptError(QAbstractSocket::SocketError socketError): 当服务器无法接受新的连接时触发该信号,可以获取错误信息。
  2. QTcpSocket 相关的回调:

    • QTcpSocket::connected(): 当套接字成功连接到远程主机时触发该信号。
    • QTcpSocket::disconnected(): 当套接字断开连接fin 位 为1时触发该信号。
    • QTcpSocket::readyRead(): 当套接字有新数据可读时触发该信号。
    • QTcpSocket::bytesWritten(qint64 bytes): 当成功写入数据到套接字时触发该信号,并返回写入的字节数。
    • QTcpSocket::error(QAbstractSocket::SocketError socketError): 当套接字发生错误时触发该信号,可以获取错误信息。
    • QTcpSocket::stateChanged(QAbstractSocket::SocketState socketState): 当套接字的连接状态发生变化时触发该信号。
    • bytesWritten(qint64 bytes) 信号:

      • 当成功写入数据到 QTcpSocket 时会触发此信号。
      • bytes 参数表示成功写入的字节数。
      • 可以用来监控数据发送的进度。
    • aboutToClose() 信号:

      • 当 QTcpSocket 将要关闭时会触发此信号。
      • 可以在此信号的槽函数中执行一些数据刷新或保存操作。
    • hostFound() 信号:

      • 当 QTcpSocket 成功解析了主机地址时会触发此信号。
      • 可以用来监控 DNS 解析的进度。
  3. QSslSocket 相关的回调(用于 SSL/TLS 连接):

    • QSslSocket::sslErrors(const QList<QSslError> &errors): 当 SSL/TLS 连接发生错误时触发该信号。
    • QSslSocket::encrypted(): 当 SSL/TLS 连接成功加密时触发该信号。
  4. QNetworkProxy 相关的回调:

    • QTcpSocket::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator): 当需要代理服务器认证时触发该信号。

这些回调接口涵盖了 TCP 连接的整个生命周期,包括连接建立、数据交互、连接断开以及各种错误情况。通过监听和处理这些信号,我们可以更好地控制和管理 TCP 连接,提高应用程序的可靠性和健壮性。

QT TCP网络通信编程项目

本地聊天传输,项目效果:

TCP服务端代码

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);setWindowTitle("TCP通讯服务端");//获取主机名和ip地址QHostInfo info =QHostInfo::fromName(QHostInfo::localHostName());QList<QHostAddress> addrs=info.addresses();if(!addrs.empty()){foreach(const QHostAddress & addr,addrs){if(addr.protocol()==QAbstractSocket::IPv4Protocol){ui->serverip->addItem(addr.toString());}}}tcpServer=new QTcpServer(this);//注册新连接回调 表示有新的客户端连接到达服务器。connect(tcpServer,&QTcpServer::newConnection,this,&MainWindow::ConnectCallback);}void MainWindow::ConnectCallback(){ //连接到达tcpSocket = tcpServer->nextPendingConnection();//连接成功后回调 表示当前 TCP 连接已经成功建立。auto clientconnect=[this](){// 客户端连接ui->plainTextEdit->appendPlainText("**********客户端socket连接成功**********");ui->plainTextEdit->appendPlainText("**********peer address:"+tcpSocket->peerAddress().toString());ui->plainTextEdit->appendPlainText("**********peer port:"+QString::number(tcpSocket->peerPort()));};connect(tcpSocket,&QTcpSocket::connected,this,clientconnect);clientconnect(); //因为当前连接已经到达了 所有手动调用一次//读前回调 当 tcpSocket 有数据可读时,该信号会被触发connect(tcpSocket,&QTcpSocket::readyRead,this,[this](){while(tcpSocket->canReadLine()){QString result = "ip:%1 prot:%2 in:%3 ";result = result.arg(tcpSocket->peerAddress().toString()).arg(QString::number(tcpSocket->peerPort())).arg(QString(tcpSocket->readLine()));ui->plainTextEdit->appendPlainText(result);}});//错误回调  当 tcpSocket 发生错误时,该信号会被触发connect(tcpSocket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),this, [this](QAbstractSocket::SocketError error) {// ui->plainTextEdit->appendPlainText("Socket error:" + error + tcpSocket->errorString());});//当套接字的连接状态发生变化时,该信号会被触发,并且会传递一个 QAbstractSocket::SocketState 类型的参数,表示当前的连接状态。connect(tcpSocket,QOverload<QAbstractSocket::SocketState>::of(&QTcpSocket::stateChanged),this,[this](QTcpSocket::SocketState state){// ui->plainTextEdit->appendPlainText("套接字状态变更:" + state);});//断开连接 fin位确认 回调connect(tcpSocket,&QTcpSocket::disconnected,this,[this](){// 客户端断开连接QString result = "**********客户端socket断开连接[ip:%1,prot:%2,]";result = result.arg(tcpSocket->peerAddress().toString()).arg(QString::number(tcpSocket->peerPort()));ui->plainTextEdit->appendPlainText(result);tcpSocket->deleteLater();});
}
MainWindow::~MainWindow()
{delete ui;if(tcpServer->isListening()){// 关闭TCP服务器tcpServer->close();tcpServer->deleteLater(); //最终关闭qDebug() << "TCP server MainWindow.";}
}
void MainWindow::closeEvent(QCloseEvent *e){ //关闭窗口//关闭closeMainWindow::on_stopServer_clicked();e->accept(); //允许窗口完成关闭操作。
}void MainWindow::on_startServer_clicked()
{QString ip(ui->serverip->currentText());uint16_t port =ui->serverport->value();tcpServer->listen(QHostAddress(ip),port);ui->plainTextEdit->appendPlainText("$$$$$$$$$$开始监听$$$$$$$$$$");ui->plainTextEdit->appendPlainText("服务器地址:"+tcpServer->serverAddress().toString());ui->plainTextEdit->appendPlainText("服务器端口:"+QString::number(tcpServer->serverPort()));ui->startServer->setEnabled(false);ui->stopServer->setEnabled(true);}void MainWindow::on_stopServer_clicked() //关闭tcpserver
{//先关闭所有socketif(!tcpSocket){tcpSocket->disconnect(); //用于断开 QTcpSocket 对象的所有信号与槽的连接。tcpSocket->close();      //它会向对端发送 FIN 数据包,并等待对端的确认,完成 TCP 连接的正常关闭过程。//fin回调 已调用 tcpSocket->deleteLater(); //它不会立即删除对象,而是将其标记为待删除状态,等到当前事件循环结束后再执行删除操作。}if(tcpServer->isListening()){tcpServer->close();//不调用 deleteLater 为了下次再次开启ui->startServer->setEnabled(true);ui->stopServer->setEnabled(false);ui->plainTextEdit->clear();}}void MainWindow::on_sendmsg_clicked()
{QString msg =ui->lineEdit->text();ui->lineEdit->clear();ui->plainTextEdit->appendPlainText("[out]:"+msg);tcpSocket->write(msg.toUtf8()+'\n');}

TCP客户端代码

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);setWindowTitle("tcp通信客户端");QHostInfo info =QHostInfo::fromName(QHostInfo::localHostName());QList<QHostAddress> addrs =info.addresses();if(!addrs.empty()){foreach(const QHostAddress& addr ,addrs){if(addr.protocol() == QAbstractSocket::IPv4Protocol){ui->serverip->addItem(addr.toString());}}}client = new QTcpSocket();//当 socket 成功连接到服务器时,会发射 connected() 信号。connect(client,&QTcpSocket::connected,this,[this](){ui->plainTextEdit->appendPlainText("**********已经连接到服务器端**********");ui->plainTextEdit->appendPlainText("服务器端ip:"+client->peerAddress().toString());ui->plainTextEdit->appendPlainText("服务器端port:"+QString::number(client->peerPort()));ui->tcpconnect->setEnabled(false);ui->tcpclose->setEnabled(true);});//当 socket 与服务器断开连接时,会发射 disconnected() 信号。connect(client,&QTcpSocket::disconnected,this,[this](){ui->plainTextEdit->appendPlainText("**********已断开与服务器端的连接**********");client->close();ui->tcpconnect->setEnabled(true);ui->tcpclose->setEnabled(false);});//当 socket 有新的数据可读时,会发射 readyRead() 信号。connect(client,&QTcpSocket::readyRead,this,[this](){while(client->canReadLine()){ui->plainTextEdit->appendPlainText("[in]:"+client->readLine());}});}MainWindow::~MainWindow()
{delete ui;
}\void MainWindow::on_send_clicked()
{QString msg=ui->lineEdit->text();ui->plainTextEdit->appendPlainText("[out]:"+msg);ui->lineEdit->clear();client->write(msg.toUtf8()+'\n');}void MainWindow::on_tcpconnect_clicked()
{QString ip=ui->serverip->currentText();quint16 port =ui->serverport->value();client->connectToHost(ip,port);if (!client->waitForConnected(3000)) {// 5s 连接超时处理逻辑ui->plainTextEdit->appendPlainText("连接超时,请检查服务器ip和port是否正确.");}}void MainWindow::on_tcpclose_clicked()
{if(client->state() ==QAbstractSocket::ConnectedState) client->disconnectFromHost(); //这里首先检查 tcpclient 对象的当前连接状态。ui->tcpconnect->setEnabled(true);ui->tcpclose->setEnabled(false);}
// 在应用程序退出或客户端断开连接时 点关闭窗口
void MainWindow::closeEvent(QCloseEvent* event) {// 1. 断开与服务器的连接if (client->state() == QAbstractSocket::ConnectedState) {client->disconnectFromHost();}qDebug()<<"closeEvent";// 2. 释放 QTcpSocket 对象client->deleteLater();// 允许窗口关闭event->accept();
}

 总结

server端

  1. TCP 服务器的创建和启停:

    • 在构造函数中创建 QTcpServer 对象,并连接 newConnection() 信号到 ConnectCallback 函数。
    • on_startServer_clicked() 函数中,监听指定的 IP 和端口,启动 TCP 服务器。
    • on_stopServer_clicked() 函数中,关闭 TCP 服务器,断开所有客户端连接。
    • 在主窗口关闭时,调用 on_stopServer_clicked() 函数关闭服务器。
  2. 客户端连接的处理:

    • 在 ConnectCallback 函数中,获取新连接的 QTcpSocket 对象。
    • 连接客户端连接成功、数据可读、错误、状态变更、断开连接等信号。
    • 在信号处理函数中,输出连接信息并处理数据收发。
  3. 数据收发和协议处理:

    • 连接 readyRead() 信号,处理客户端发送的数据。
    • 使用 tcpSocket->readLine() 读取并解析数据,输出到 UI 界面。
    • on_sendmsg_clicked() 函数中,通过 tcpSocket->write() 将消息发送给客户端。
  4. 异常处理:

    • 连接 error() 信号,处理套接字错误。
    • 连接 stateChanged() 信号,监控连接状态变更。
  5. 生命周期管理:

    • 在主窗口析构函数中,关闭 TCP 服务器并释放资源。
    • 在客户端断开连接时,释放 QTcpSocket 对象。

通过学习这段代码,我们可以掌握以下 Qt TCP 编程的关键点:

  1. 如何创建 TCP 服务器并监听端口。
  2. 如何处理新的客户端连接,并与之进行数据通信。
  3. 如何处理连接错误和状态变更。
  4. 如何优雅地关闭服务器并释放资源。

客户端

  1. TCP 客户端的创建和连接:

    • 在构造函数中创建 QTcpSocket 对象 client
    • 连接 connected() 信号,处理与服务器成功连接的情况。
    • on_tcpconnect_clicked() 函数中,调用 connectToHost() 连接到服务器。
    • 使用 waitForConnected() 处理连接超时的情况。
  2. 数据收发和协议处理:

    • 连接 readyRead() 信号,处理服务器发送的数据。
    • 使用 client->readLine() 读取并解析数据,输出到 UI 界面。
    • on_send_clicked() 函数中,通过 client->write() 将消息发送给服务器。
  3. 连接状态管理:

    • 连接 disconnected() 信号,处理与服务器的断开连接。
    • 在 closeEvent() 中,检查连接状态并断开连接。
    • 更新 UI 按钮的状态,反映当前的连接状态。
  4. 异常处理:

    • 在连接超时的情况下,输出错误提示信息。
    • 在 closeEvent() 中,释放 QTcpSocket 对象。

通过学习这段代码,我们可以掌握以下 Qt TCP 客户端编程的关键点:

  1. 如何创建 TCP 客户端并连接到服务器。
  2. 如何处理数据的收发,并按照约定的协议进行解析。
  3. 如何管理连接状态,处理连接成功、断开等情况。
  4. 如何优雅地关闭连接并释放资源。

    

最后附上源代码链接
对您有帮助的话,帮忙点个star

35-tcpSocket-client · jbjnb/Qt demo - 码云 - 开源中国 (gitee.com)

35-tcpSocket-server · jbjnb/Qt demo - 码云 - 开源中国 (gitee.com)

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

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

相关文章

云原生之容器编排实践-OpenEuler23.09在线安装Kubernetes与KubeSphere

背景 前几篇文章中介绍了如何将 ruoyi-cloud 项目部署到 Kubernetes 集群中&#xff0c;包括网关服务、认证服务和系统服务并且对全部服务采用 YAML 文件的方式来进行部署&#xff0c;这虽然有助于理解 K8S 组织管理资源的风格与底层机制&#xff0c;但是对于团队中不太熟悉命…

Lunaproxy与711Proxy的对比与优劣分析

今天我们来深入对比两款在市场上备受关注的代理IP服务&#xff1a;Lunaproxy和711Proxy。接下来&#xff0c;我们将从多个角度对这两款服务进行详细分析&#xff0c;帮助大家做出明智的选择。 优势分析 711Proxy的优势 1. 性价比高&#xff1a;711Proxy提供多种灵活的套餐选…

【JavaWeb程序设计】JSP编程II

目录 一、输入并运行下面的import_test.jsp页面 1.1 代码运行结果 1.2 修改编码之后的运行结果 二、errorPage属性和isErrorPage属性的使用 2.1 下面的hello.jsp页面执行时将抛出一个异常&#xff0c;它指定了错误处理页面为errorHandler.jsp。 2.1.2 运行截图 2.2 下面…

VBA初学:零件成本统计之一(任务汇总)

经过前期一年多对金蝶K3生产任务流程和操作的改造和优化&#xff0c;现在总算可以将零件加工各个环节的成本进行归集了。 原本想写存储过程&#xff0c;通过直接SQL报表做到K3中去的&#xff0c;但财务原本就是用EXCEL&#xff0c;可以方便调整和保存&#xff0c;加上还有一部分…

mybatis-plus参数绑定异常

前言 最近要搞个发票保存的需求&#xff0c;当发票数据有id时说明是发票已经保存只需更新发票数据即可&#xff0c;没有id时说明没有发票数据需要新增发票&#xff1b;于是将原有的发票提交接口改造了下&#xff0c;将调用mybatis-plus的save方法改为saveOrUpdate方法&#xff…

芯片基识 | 掰开揉碎讲 FIFO(同步FIFO和异步FIFO)

文章目录 一、什么是FIFO二、为什么要用FIFO三、什么时候用FIFO四、FIFO分类五、同步FIFO1. 同步FIFO电路框图2. 同步FIFO空满判断3. 同步FIFO设计代码4. 同步FIFO仿真结果 六、异步FIFO1、异步FIFO的电路框图2 、亚稳态3、打两拍4、格雷码5、如何判断异步FIFO的空满&#xff0…

Spring boot 更改启动LOGO

在resources目录下创建banner.txt文件&#xff0c;然后编辑对应的图案即可 注释工具 Spring Boot Version: ${spring-boot.version},-.___,---.__ /|\ __,---,___,- \ -.____,- | -.____,- // -., | ~\ /~ | …

Go语言--工程管理、临时/永久设置GOPATH、main函数以及init函数

工作区 Go 代码必须放在工作区中。工作区其实就是一个对应于特定工程的目录&#xff0c;它应包含3个子目录:src 目录、pkg目录和bin 目录。 src 目录:用于以代码包的形式组织并保存 Go源码文件。(比如:.go.chs等)pkg 目录:用于存放经由 go install 命令构建安装后的代码包(包…

1119 胖达与盆盆奶

solution 递推&#xff1a;序列的每一位所需要计算的值都可以通过该位左右两侧的结果计算得到&#xff0c;就可以考虑所谓的“左右两侧的结果”是否能通过递推进行预处理来得到&#xff0c;以避免后续使用中的反复求解。 #include<iostream> using namespace std; cons…

Xilinx FPGA:vivado关于fifo的一些零碎知识

一、FIFO概念 先进先出&#xff0c;是一种组织和操作数据结构的方法。在硬件应用中&#xff0c;FIFO一般由一些读写指针&#xff0c;存储和控制的逻辑组成。 二、xilinx中生成的FIFO的存储类型 &#xff08;1&#xff09;shift register FIFO : 移位寄存器FIFO&#xff0c;这…

java Web 优秀本科毕业论文系统用eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 JSP 优秀本科毕业论文系统是一套完善的web设计系统&#xff0c;对理解JSP java serlvet 编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发&#xff0c;数据库为Mysql5.0&a…

CTF常用sql注入(三)无列名注入

0x06 无列名 适用于无法正确的查出结果&#xff0c;比如把information_schema给过滤了 join 联合 select * from users;select 1,2,3 union select * from users;列名被替换成了1,2,3&#xff0c; 我们再利用子查询和别名查 select 2 from (select 1,2,3 union select * f…

笔记12:if语句编程练习(打印输出三个数据中的最小值)

输入三个数&#xff0c;分别放入变量x&#xff0c;y&#xff0c;z中 打印输入数据中最小的那一个数 解决方案1 定义中间变量 t 1.比较x和y的大小关系&#xff0c;将较小的值赋值给t 2.比较t和z的大小关系&#xff0c;将较小的值赋值给t 3.t 中保存的就是3个数中的较小值 &am…

【数据结构】常见四类排序算法

1. 插入排序 1.1基本思想&#xff1a; 直接插入排序是一种简单的插入排序法&#xff0c;其基本思想是&#xff1a;把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中&#xff0c;直到所有的记录插入完为止&#xff0c;得到一个新的有序序列 。实际中我们…

十大排序:插入/希尔/选择/堆/冒泡/快速/归并/计数/基数/桶排序 汇总(C语言)

目录 前言非线性时间比较类插入排序(1) 直接插入排序(2) 希尔排序 选择排序(3) 选择排序优化版(4) 堆排序 交换排序(5) 冒泡排序(6) 快速排序hoare版本挖坑版前后指针版非递归版 归并排序(7) 归并排序递归版非递归版 线性时间比较类(8) 计数排序基数排序与桶排序 总结 前言 在计…

Redis哨兵和集群模式

特性哨兵模式集群模式高可用性是是数据分片否是水平扩展否是配置复杂度低高管理复杂度低高多键操作支持是否&#xff08;有限制&#xff09; 哨兵模式 原理&#xff1a; Redis 哨兵模式是一种高可用性解决方案&#xff0c;它通过监控 Redis 主从架构&#xff0c;自动执行故障…

STM32第十五课:LCD屏幕及应用

文章目录 需求一、LCD显示屏二、全屏图片三、数据显示1.显示欢迎词2.显示温湿度3.显示当前时间 四、需求实现代码 需求 1.在LCD屏上显示一张全屏图片。 2.在LCD屏上显示当前时间&#xff0c;温度&#xff0c;湿度。 一、LCD显示屏 液晶显示器&#xff0c;简称 LCD(Liquid Cry…

vulhub靶场之DEVGURU:1

1 信息收集 1.1 主机发现 arp-scan -l 发现主机IP地址为“192.168.1.11 1.2 端口发现 nmap -sS -sV -A -T5 -p- 192.168.1.11 发现端口为&#xff1a;22&#xff0c;80&#xff0c;8585 1.3 目录扫描 dirsearch -u 192.168.1.11 发现存在git泄露 2 文件和端口访问 2…

【JavaEE精炼宝库】文件操作(1)——基本知识 | 操作文件——打开实用性编程的大门

目录 一、文件的基本知识1.1 文件的基本概念&#xff1a;1.2 树型结构组织和目录&#xff1a;1.3 文件路径&#xff08;Path&#xff09;&#xff1a;1.4 二进制文件 VS 文本文件&#xff1a;1.5 其它&#xff1a; 二、Java 操作文件2.1 方法说明&#xff1a;2.2 使用演示&…

Python学习笔记29:进阶篇(十八)常见标准库使用之质量控制中的数据清洗

前言 本文是根据python官方教程中标准库模块的介绍&#xff0c;自己查询资料并整理&#xff0c;编写代码示例做出的学习笔记。 根据模块知识&#xff0c;一次讲解单个或者多个模块的内容。 教程链接&#xff1a;https://docs.python.org/zh-cn/3/tutorial/index.html 质量控制…