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():停止监听并关闭服务器。
      • abort()是强行立即关闭连接,相当于调用disconnectFromHost()。关闭后会释放所有相关资源并触发 QAbstractSocket::abort信号。对端可能不知道连接已经关闭。

      • close()是通过标准关闭序列完成关闭,等待对端确认,保证数据完整性。它会优雅地关闭socket连接,先发送关闭请求给对端,并等待对端确认。然后会进入关闭状态,触发QAbstractSocket::stateChanged(QAbstractSocket::ClosingState)和QAbstractSocket::disconnected信号。

    • 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){ //关闭窗口
    //关闭close
    MainWindow::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
{
    //先关闭所有socket
    if(!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 对象。
      • 如果需要立即关闭连接而不管数据完整性,使用abort()。

      • 如果需要负责任关闭保证数据完整,则使用close()。

通过学习这段代码,我们可以掌握以下 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)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【区块链 + 智慧政务】省级一体化区块链平台 | FISCO BCOS应用案例

在加强数字政府建设的大背景下&#xff0c;科大讯飞广泛应用数字技术于政府管理服务&#xff0c;推动政府数字化、智能化运行。同时&#xff0c; 统筹推进业务、数据和技术的融合&#xff0c;提升跨地域、跨层级、跨部门和跨业务的协同管理和服务水平。 当前政务信息化建设中&…

绿盟培训入侵排查

一、webshell 排查 1、文件特征 2、windows 3、linux 4、内存马 二、web 日志排查 1、日志排查 2、中间件报错排查 三、服务器失陷处置

洛谷 7.10 数数

Vanya and Books - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) ac代码 #include<bits/stdc.h> typedef long long ll;#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0) const ll N1e3; using namespace std;int main() {IOS;ll x;cin>>x;ll ans0,px…

VScode 格式化插件Prettier设置无效

VScode在配置格式化代码的插件的时候&#xff0c;可以选择Prettier或者ESlint等插件 比如选择Prettier格式化代码 在某文件修改代码之后&#xff0c;ctrls 保存代码&#xff0c;保存之后会自动格式化代码&#xff0c;但是我们发现控制台有报错 为什么已经设置了格式化插件为Pr…

Springboot 设置个性化banner

在 Spring Boot 中自定义 banner 的方法有几种&#xff0c;可以通过以下步骤来实现&#xff1a; 1、使用文本文件作为 banner 在 src/main/resources 目录下创建一个名为 banner.txt 的文件。 编辑这个文件&#xff0c;输入想要显示的文本。确保文本中包含换行符和空格…

linux radix-tree 基数树实现详解

radix tree&#xff0c;又称做基数树&#xff0c;是一种适合于构建key(index)与value(item)相关联的数据结构。内核中使用非常广泛。本文主要聚焦linux内核基数树的代码实现,大量注释过的代码。 radix-tree组织结构如下: 1、数据结构 /** The bottom two bits of the slot de…

Java中的公平锁和非公平锁

1、什么是公平锁和非公平锁 公平锁和非公平锁是指在多线程环境下&#xff0c;如何对锁进行获取的顺序和策略的不同。 公平锁是指多个线程按照申请锁的顺序来获取锁&#xff0c;即先到先得的策略。当一个线程释放锁之后&#xff0c;等待时间最长的线程将获得锁。公平锁的优点是保…

MySQL六:内置函数

文章目录 1. 日期函数2. 字符串函数3. 数学函数4. 其它函数 1. 日期函数 2. 字符串函数 函数名描述charset(str)返回字符串字符集concat(string2 [,…])连接字符串instr(string&#xff0c;substring)返回substring在string中出现的位置&#xff0c;没有返回0ucase(string2)转…

甘肃美食于兰洽会数智电商馆展现魅力

在近日盛大开幕的兰洽会上&#xff0c;数智电商馆成为了备受瞩目的焦点&#xff0c;而甘肃平凉的特产更是在其中大放异彩。 平凉&#xff0c;这座拥有深厚历史文化底蕴的城市&#xff0c;带着其独具特色的物产走进了兰洽会的舞台。走进数智电商馆&#xff0c;首先映入眼帘的便是…

MySQL安全值守常用语句

一、用户权限设置 1、Mysql中用户是如何定义的 用户名主机域 10.0.0.5110.0.0.%%10.0.0.0/255.255.255.0Db01Localhost127.0.0.1 2、用户创建 create user xinjing% identified by 123 3、用户删除 drop user username&#xff1b;username 是要删除的用户名:如 drop user root…

WPF界面设计-更改按钮样式 自定义字体图标

一、下载图标文件 iconfont-阿里巴巴矢量图标库 二、xaml界面代码编辑 文件结构 &#xe653; 对应的图标代码 Fonts/#iconfont 对应文件位置 <Window.Resources><ControlTemplate TargetType"Button" x:Key"CloseButtonTemplate"…

做谷歌seo多少钱,一年一个月的费用详细

在当今全球化的商业环境中&#xff0c;谷歌SEO&#xff08;搜索引擎优化&#xff09;已成为企业拓展国际市场、提升品牌知名度及吸引潜在客户的关键策略之一。然而&#xff0c;对于许多企业来说&#xff0c;了解并规划谷歌SEO的全年费用结构是一个既复杂又重要的任务。 本文将…

Echarts中的折线图,多个Y轴集中在左侧(在Vue中使用多个Y轴的折线图)

简述&#xff1a;在 ECharts 中&#xff0c;创建一个带有多个 Y 轴的折线图&#xff0c;并且将这些 Y 轴都集中显示在图表的左侧&#xff0c;可以通过合理配置 yAxis 和 series 的属性来实现。简单记录 一. 函数代码 drawCarNumEcs() {// 初始化echarts图表,并绑定到id为"…

Selenium 中的 JUnit 注解

JUnit 是一个基于 Java 的开源框架&#xff0c;可帮助测试人员执行单元测试。JUnit 主要用于测试应用程序的每个单元或组件&#xff0c;例如类和方法。它有助于编写和运行可重复的自动化测试&#xff0c;以确保项目代码按预期运行。还可以使用 JUnit 执行 Selenium 自动化测试用…

Python 利用pandas处理CSV文件(DataFrame的基础用法)

前面介绍过通过Python标准库中的CSV模块处理CSV文件&#xff1a; Python 利用CSV模块处理数据 相比CSV模块&#xff0c;pandas的功能更加强大&#xff0c;本文将简单介绍如何通过pandas来处理CSV文件。 文章目录 一、pandas简介二、用法示例2.1 读取CSV文件2.1.1 read_csv参数…

Databricks 收购 Tabular 的意义:数据开放框架的胜利

Databricks 宣布收购 Tabular&#xff0c;这是一个由 Apache Iceberg 的原始创建者开发的数据平台&#xff0c;在数据分析行业引发了涟漪。此次收购凸显了开放框架在数据领域日益增长的重要性&#xff0c;预示着数据管理、分析和 AI/ML 计划领域的创新、协作和可访问性的新时代…

Prometheus+Grafana主机运行数据

目录 介绍 安装Node Exporter 配置Prometheus 验证配置 导入仪表盘 介绍 Prometheus是一款开源的监控和警报工具&#xff0c;而Node Exporter是Prometheus的一个官方插件&#xff0c;用于采集主机上的各种系统和硬件指标。 安装Node Exporter 下载最新版本的Node Export…

盲盒抽卡机小程序:抽卡机的多样化发展

近几年&#xff0c;盲盒卡牌出现在了大众的生活中&#xff0c;深受学生和年轻消费者的喜爱。卡牌是一种新的盲盒模式&#xff0c;玩家购买后随机获得卡牌&#xff0c;为了收集一整套卡牌&#xff0c;玩家会进行各种复购行为&#xff0c;卡牌逐渐成为了年轻人追捧的休闲方式&…

雨量监测站的重要性有哪些

在全球气候变化和极端天气事件频发的背景下&#xff0c;雨量监测站成为了我们理解降水模式、预测天气变化以及制定应对措施的重要工具。 雨量监测站是一种专门用于测量和记录降水量的设施。它们通过配备高精度的雨量传感器&#xff0c;能够实时监测降雨情况&#xff0c;并提供关…

​​​​​​​生物素化药物分子的特性

生物素化药物分子是指将生物素&#xff08;维生素H&#xff0c;也称维生素B7或维生素B8&#xff09;共价连接到药物分子上的过程。这种处理方式为药物分子带来了多种特性和优势&#xff0c;以下是对生物素化药物分子的详细解析&#xff1a; 一、生物素的基本特性 生物素是一种水…