WebSocket的原理及QT示例

一.WebSocket 介绍

1.概述

WebSocket 是一种在单个 TCP 连接上进行全双工通讯的协议,它在 2011 年被 IETF 定为标准 RFC 6455,并由 RFC7936 补充规范。与传统的 HTTP 协议不同,WebSocket 允许服务器和客户端之间进行实时、双向的数据传输,打破了 HTTP 协议请求 - 响应的模式限制,大大提高了数据传输的效率和实时性。

2.特点

全双工通信:服务器和客户端可以在任意时刻向对方发送数据,无需等待对方的请求。

实时性强:由于采用了全双工通信,数据可以即时传输,非常适合实时性要求较高的应用场景,如在线聊天、实时数据监控等。

较少的开销:WebSocket 握手阶段使用 HTTP 协议,建立连接后,数据传输不再需要像 HTTP 那样携带大量的头部信息,减少了数据传输的开销。

跨域支持:WebSocket 支持跨域通信,方便不同域名之间的服务器和客户端进行数据交互。

客户端与服务器交互图

3.应用场景

实时聊天应用:如在线客服、社交聊天等,用户可以即时收到对方发送的消息。

实时数据监控:如股票行情、传感器数据监控等,服务器可以实时将最新的数据推送给客户端。

多人在线游戏:实现游戏中玩家之间的实时交互,如位置更新、动作同步等。

二.代码示例

1.客户端代码

#include "Clientdialog.h"

#include <QLabel>

#include <QWidget>

#include <QHBoxLayout>

#include <QVBoxLayout>

#include <QtCore>

#include <QDebug>

#include <iostream>

ClientDialog::ClientDialog(QWidget *parent)

    : QWidget(parent)

{

    //layout1

    QLabel *iplabel = new QLabel("Server IP");

    m_iplineedit =new QLineEdit;

    m_iplineedit->setText("127.0.0.1");

    QLabel *portlabel =new QLabel("Server端口");

    m_portspinbox = new QSpinBox;

    m_portspinbox->setRange(0,65535);

    m_portspinbox->setValue(5123);

    m_linkbutton = new QPushButton("连接");

    m_disconnectbutton = new QPushButton("断开");

    pButtonGroup = new QButtonGroup();

    pButtonGroup->setExclusive(true);

    m_linkbutton->setCheckable(true);

    m_disconnectbutton->setCheckable(true);

    pButtonGroup->addButton(m_linkbutton,0);

    pButtonGroup->addButton(m_disconnectbutton,1);

    QHBoxLayout *qhboxlayout1 = new QHBoxLayout;

    qhboxlayout1->addWidget(iplabel);

    qhboxlayout1->addWidget(m_iplineedit);

    qhboxlayout1->addWidget(portlabel);

    qhboxlayout1->addWidget(m_portspinbox);

    qhboxlayout1->addWidget(m_linkbutton);

    qhboxlayout1->addWidget(m_disconnectbutton);

    //layout2

    QLabel *sendmessagelabel = new QLabel("发送消息");

    QHBoxLayout *qhboxlayout2 = new QHBoxLayout;

    qhboxlayout2->addWidget(sendmessagelabel);

    //layout3

    m_sendmessagetextedit = new QTextEdit;

    m_sendmessagetextedit->setFixedHeight(50);

    m_sendbutton = new QPushButton("发送");

    m_sendbutton->setFixedHeight(50);

    QHBoxLayout *qhboxlayout3 = new QHBoxLayout;

    qhboxlayout3->addWidget(m_sendmessagetextedit);

    qhboxlayout3->addWidget(m_sendbutton);

    //layout4

    QLabel *receivemessagelabel = new QLabel("接收消息");

    QHBoxLayout *qhboxlayout4 = new QHBoxLayout;

    qhboxlayout4->addWidget(receivemessagelabel);

    //layout5

    m_receivemessageTextEdit = new QTextEdit;

    QHBoxLayout *qhboxlayout5 = new QHBoxLayout;

    qhboxlayout5->addWidget(m_receivemessageTextEdit);

    m_receivemessageTextEdit->setReadOnly(true);

    //layout6

    statusLabel = new QLabel("连接状态");

    m_clean = new QPushButton("清除");

    QHBoxLayout *qhboxlayout6 = new QHBoxLayout;

    qhboxlayout6->addWidget(statusLabel);

    qhboxlayout6->addStretch();

    qhboxlayout6->addWidget(m_clean);

    //

    QVBoxLayout *mainlayout = new QVBoxLayout;

    mainlayout->addLayout(qhboxlayout1,1);

    mainlayout->addLayout(qhboxlayout2,0.5);

    mainlayout->addLayout(qhboxlayout3,1);

    mainlayout->addLayout(qhboxlayout4,0.5);

    mainlayout->addLayout(qhboxlayout5,3);

    mainlayout->addLayout(qhboxlayout6,1);

    setLayout(mainlayout);

    setWindowTitle("Websocket Client");

    this->setFixedSize(800, 600); // 窗口固定为800x600像素,无法缩放

    connect(m_linkbutton,SIGNAL(clicked(bool)),this,SLOT(connectToServer()));

    connect(m_disconnectbutton,SIGNAL(clicked(bool)),this,SLOT(stopClicked()));

    connect(m_sendbutton,SIGNAL(clicked(bool)),this,SLOT(onSendButtonClicked()));

    connect(m_clean,SIGNAL(clicked(bool)),this,SLOT(onCleanButtonClicked()));

    connect(&m_websocket,SIGNAL(connected()),this,SLOT(onconnected()));

    connect(&m_websocket,SIGNAL(disconnected()),this,SLOT(closeConnection()));

    connect(&m_websocket,SIGNAL(textMessageReceived(QString)),this,SLOT(onTextMessageReceived(QString)));

}

ClientDialog::~ClientDialog()

{

    m_websocket.errorString();

    m_websocket.close();

}

//断开连接操作

void ClientDialog::closeConnection(){

    m_linkbutton->setEnabled(true);

    m_disconnectbutton->setEnabled(false);

    m_sendmessagetextedit->setEnabled(false);

    m_sendbutton->setEnabled(false);

    m_receivemessageTextEdit->setEnabled(false);

    m_clean->setEnabled(false);

    statusLabel->setText(tr("disconnected"));

}

//连接服务器

void ClientDialog::connectToServer()

{

    QString path = QString("ws://%1:%2").arg(m_iplineedit->text()).arg(m_portspinbox->text());

    QUrl url = QUrl(path);

    m_websocket.open(url);

}

//连接上之后

void ClientDialog::onconnected(){

    qDebug() << "hello word!";

    statusLabel->setText(tr("connected"));

    m_linkbutton->setEnabled(false);

    m_disconnectbutton->setEnabled(true);

    m_sendmessagetextedit->setEnabled(true);

    m_sendbutton->setEnabled(true);

    m_receivemessageTextEdit->setEnabled(true);

    m_clean->setEnabled(true);

}

//收到消息

void ClientDialog::onTextMessageReceived(const QString &message)

{

    QString time = current_date_time->currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz ddd");

    m_receivemessageTextEdit->setText(time + "\r\n" + "message: " + message);

}

//断开

void ClientDialog::stopClicked()

{

    m_websocket.close();

}

//发送消息

void ClientDialog::onSendButtonClicked()

{

    QString msg= m_sendmessagetextedit->document()->toPlainText();

    m_websocket.sendTextMessage(msg);

}

//清除内容

void ClientDialog::onCleanButtonClicked()

{

    m_receivemessageTextEdit->clear();

}

2.服务端代码

#include "webserver.h"

#include "ui_webserver.h"

#include <QtCore/QVariant>

#include <QtWidgets/QApplication>

#include <QtWidgets/QButtonGroup>

#include <QtWidgets/QHeaderView>

#include <QtWidgets/QLabel>

#include <QtWidgets/QListWidget>

#include <QtWidgets/QPushButton>

#include <QtWidgets/QSpinBox>

#include <QtWidgets/QTextBrowser>

#include <QtWidgets/QWidget>

#include <QHBoxLayout>

webserver::webserver(QWidget *parent) :

    QWidget(parent),

    ui(new Ui::webserver)

{

    ui->setupUi(this);

    {

         //qhboxLayout1部分代码

         QLabel* monitorLabel= new QLabel("监听端口");

         m_monitorSpinBox = new QSpinBox();

         m_monitorSpinBox->setRange(0,65535);

         m_monitorSpinBox->setValue(5123);

         m_startButton = new QPushButton("启动服务");

         m_stopButton = new QPushButton("停止服务");

         m_stopButton->setEnabled(false);

         QHBoxLayout *qhboxLayout = new QHBoxLayout;

         qhboxLayout->addWidget(monitorLabel);

         qhboxLayout->addWidget(m_monitorSpinBox);

         qhboxLayout->addWidget(m_startButton);

         qhboxLayout->addWidget(m_stopButton);

        //qhboxLayout2部分代码

          QLabel* sendLabel=new QLabel("发送消息");

          sendLabel->setFixedHeight(30);

          QHBoxLayout *qhboxLayout2 = new QHBoxLayout;

          qhboxLayout2->addWidget(sendLabel);

        //qhboxLayout3部分代码

          m_sendTextedit = new QTextEdit;

          m_sendTextedit = new QTextEdit();

          m_sendTextedit->setEnabled(false);

          m_sendTextedit->setFixedHeight(80);

          m_sendButton= new QPushButton("发送");

          m_sendButton->setEnabled(false);

          m_sendButton->setFixedHeight(50);

          QHBoxLayout *qhboxlayout3 = new QHBoxLayout;

          qhboxlayout3->addWidget(m_sendTextedit,2);

          qhboxlayout3->addWidget(m_sendButton,1);

        //qvboxlayout411

          QLabel* receiveLabel = new QLabel("接收消息");

          receiveLabel->setFixedHeight(30);

          m_receiveTextEdit = new QTextEdit();

          m_receiveTextEdit->setReadOnly(true);

          QVBoxLayout *qvboxlayout411 = new QVBoxLayout;

          qvboxlayout411->addWidget(receiveLabel);

          qvboxlayout411->addWidget(m_receiveTextEdit);

            //qhboxlayout412

          m_cleanButton = new QPushButton("清除");

          m_cleanButton->setEnabled(false);

          QHBoxLayout *qhboxlayout412 = new QHBoxLayout;

          qhboxlayout412->addStretch();

          qhboxlayout412->addWidget(m_cleanButton);

        //qvboxlayout41

          QVBoxLayout *qvboxlayout41 = new QVBoxLayout;

          qvboxlayout41->addLayout(qvboxlayout411);

          qvboxlayout41->addLayout(qhboxlayout412);

        //qvboxlayout42

          QLabel* linkclientLabel=new QLabel("连接客户端");

          linkclientLabel->setFixedHeight(30);

          m_linkclientListWidget=new QListWidget;

          QVBoxLayout* qvboxlayout42 = new QVBoxLayout;

          qvboxlayout42->addWidget(linkclientLabel);

          qvboxlayout42->addWidget(m_linkclientListWidget);

        //qvboxlayout4

          QHBoxLayout *qhboxlayout4 = new QHBoxLayout;

          qhboxlayout4->addLayout(qvboxlayout41,2);

          qhboxlayout4->addLayout(qvboxlayout42,1);

         //mainlayout

          QVBoxLayout *mainLayout = new QVBoxLayout;

          mainLayout->addLayout(qhboxLayout,1);

          mainLayout->addLayout(qhboxLayout2,1);

          mainLayout->addLayout(qhboxlayout3,1);

          mainLayout->addLayout(qhboxlayout4,3);

          this->setLayout(mainLayout);

          this->setWindowTitle("Websocket Server -- Neo");

          this->setFixedSize(800, 600); // 窗口固定为800x600像素,无法缩放

    }

    m_WebSocketServer=new QWebSocketServer("server",QWebSocketServer::NonSecureMode);

    connect(m_WebSocketServer,SIGNAL(newConnection()),this,SLOT(onNewConnection()));

    connect(m_WebSocketServer, SIGNAL(closed()), this, SLOT(onClosed()));

    connect(m_WebSocketServer, SIGNAL(serverError(QWebSocketProtocol::CloseCode)),

            this, SLOT(onServerError(QWebSocketProtocol::CloseCode)));

    connect(m_startButton,SIGNAL(clicked(bool)),this,SLOT(onStartButtonClick()));

    connect(m_stopButton,SIGNAL(clicked(bool)),this,SLOT(onStopButtonClick()));

    connect(m_cleanButton,SIGNAL(clicked(bool)),this,SLOT(onCleanButtonClick()));

    connect(m_sendButton,SIGNAL(clicked(bool)),this,SLOT(onSendButtonClick()));

}

webserver::~webserver()

{

    if(m_WebSocketServer)

    {

        m_WebSocketServer->close();

    }

    delete ui;

}

//开启服务

void webserver::onStartButtonClick(){

    int i_port = m_monitorSpinBox->text().toInt();

    m_WebSocketServer->listen(QHostAddress::Any,i_port);

    m_startButton->setEnabled(false);

    m_stopButton->setEnabled(true);

    qDebug()<<m_WebSocketServer->isListening();

    qDebug()<<m_WebSocketServer->serverPort();

    qDebug()<<m_WebSocketServer->serverAddress();

}

//停止服务

void webserver::onStopButtonClick(){

    m_startButton->setEnabled(true);

    m_stopButton->setEnabled(false);

    m_WebSocketServer->close();

}

//发送信息

void webserver::onSendButtonClick(){

    QString msg = m_sendTextedit->document()->toPlainText();

    int currenRow = m_linkclientListWidget->currentRow();//当前单击选中ListWidget控件的行号

    if(currenRow==-1)

    {

        currenRow = 0;

    }

    QString key = m_linkclientListWidget->item(currenRow)->text();

    if(_hashIpPort2PWebSocket.contains(key))

    {

        _hashIpPort2PWebSocket.value(key)->sendTextMessage(msg);

    }

}

void webserver::onCleanButtonClick(){

    m_receiveTextEdit->clear();

}

//连接上之后

void webserver::onNewConnection(){

    qDebug() << "connect ok";

    m_startButton->setEnabled(false);

    m_stopButton->setEnabled(true);

    m_sendTextedit->setEnabled(true);

    m_sendButton->setEnabled(true);

    m_cleanButton->setEnabled(true);

    QWebSocket *pWebSocket = m_WebSocketServer->nextPendingConnection();

    connect(pWebSocket,SIGNAL(textMessageReceived(QString)),this,SLOT(slot_processTextMessage(QString)));

    connect(pWebSocket,SIGNAL(disconnected()),this,SLOT(slot_socketDisconnected()));

    connect(pWebSocket, SIGNAL(error(QAbstractSocket::SocketError)),

            this      , SLOT(slot_error(QAbstractSocket::SocketError)));

    quint32 ipv4Address =  pWebSocket->peerAddress().toIPv4Address();

    QString ipString = QHostAddress(ipv4Address).toString();

    _hashIpPort2PWebSocket.insert(QString("%1-%2").arg(ipString).arg(pWebSocket->peerPort()),pWebSocket);

    QString item = QString("%1-%2").arg(ipString).arg(pWebSocket->peerPort());

    m_linkclientListWidget->addItem(item);

}

//停止之后

void webserver::onClosed()

{

    QList<QWebSocket *> _listWebSocket = _hashIpPort2PWebSocket.values();

    for(int index = 0; index < _listWebSocket.size(); index++)

    {

        _listWebSocket.at(index)->close();

    }

    _hashIpPort2PWebSocket.clear();

    m_linkclientListWidget->clear();

}

//连接错误

void webserver::onServerError(QWebSocketProtocol::CloseCode closeCode)

{

    QWebSocket *pWebSocket = dynamic_cast<QWebSocket *>(sender());

    if(!pWebSocket)

    {

        return;

    }

}

void webserver::slot_error(QAbstractSocket::SocketError error)

{

    QWebSocket *pWebSocket = dynamic_cast<QWebSocket *>(sender());

    if(!pWebSocket)

    {

        return;

    }

}

//收到消息并显示

void webserver::slot_processTextMessage(QString message){

    QWebSocket *pWebSocket = dynamic_cast<QWebSocket *>(sender());

    if(!pWebSocket)

    {

        return;

    }

    QString time = current_date_time->currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz ddd");

    quint32 ipv4Address =  pWebSocket->peerAddress().toIPv4Address();

    QString ipString = QHostAddress(ipv4Address).toString();

    QString item = QString("IP: %1, port: %2").arg(ipString).arg(pWebSocket->peerPort());

    m_receiveTextEdit->append(time+ "\r\n" + item + "\r\n" + "message: " + message + "\r\n");

    //qDebug()<< pWebSocket->peerAddress().toString();

    //qDebug() << "Client IP address: " << ipString;

}

//连接断开的操作

void webserver::slot_socketDisconnected(){

    QWebSocket *pWebSocket = dynamic_cast<QWebSocket *>(sender());

    if(!pWebSocket)

    {

        return;

    }

    //qDebug() << __FILE__ << __LINE__ << __FUNCTION__;

    quint32 ipv4Address =  pWebSocket->peerAddress().toIPv4Address();

    QString ipString = QHostAddress(ipv4Address).toString();

    QString item1 = QString("%1-%2").arg(ipString).arg(pWebSocket->peerPort());

    _hashIpPort2PWebSocket.remove(QString("%1-%2").arg(ipString).arg(pWebSocket->peerPort()));

    QListWidgetItem *item3;

    for(int i=0;i<m_linkclientListWidget->count();i++)

    {

        QString str = m_linkclientListWidget->item(i)->text();

        if(str == item1)

        {

            item3 = m_linkclientListWidget->takeItem(i);

            m_linkclientListWidget->removeItemWidget(item3);

            delete item3;

        }

    }

}

void webserver::on_m_linkclientListWidget_clicked(const QModelIndex &index)

{

int currenRow = m_linkclientListWidget->currentRow();

}

3.完整工程代码下载

https://download.csdn.net/download/xieliru/90787178

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

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

相关文章

设置GO程序在离线情况下读取本地缓存的模块

在 Go 中&#xff0c;GOPROXY 环境变量用于指定模块代理服务器的地址。如果你想让 GOPROXY 读取本地的模块&#xff0c;可以通过以下几种方式实现&#xff1a; 1. 使用本地代理服务器 你可以搭建一个本地的 Go 模块代理服务器&#xff0c;将需要的模块代码推送到代理服务器中…

live555开发笔记(三):live555创建RTSP服务器源码剖析,创建h264文件rtsp服务器源码深度剖析

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/147879917 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

STM32-模电

目录 一、MOS管 二、二极管 三、IGBT 四、运算放大器 五、推挽、开漏、上拉电阻 一、MOS管 1. MOS简介 这里以nmos管为例&#xff0c;注意箭头方向。G门极/栅极&#xff0c;D漏极&#xff0c;S源极。 当给G通高电平时&#xff0c;灯泡点亮&#xff0c;给G通低电平时&a…

基于定制开发开源AI智能名片S2B2C商城小程序的公私域流量融合运营策略研究

摘要&#xff1a;本文以定制开发开源AI智能名片S2B2C商城小程序为技术载体&#xff0c;系统探讨公域流量向私域流量沉淀的数字化路径。研究通过分析平台流量&#xff08;公域流量&#xff09;与私域流量的共生关系&#xff0c;提出"公域引流-私域沉淀-数据反哺"的闭环…

mysql中索引的使用

前言 最近一直在学习mysql以及忙学校课程的事情。已经好久没写过博客了&#xff0c;今天跟大家分享一下在mysql中关于索引的知识&#xff0c;希望可以帮助到大家。 索引的定义 mysql中的索引是一种数据结构&#xff0c;它可以帮助数据库高效地查询&#xff0c;更新数据表中的…

深度拆解!MES如何重构生产计划与排产调度全流程?

☂引言 在制造业数字化转型浪潮中&#xff0c;生产计划与排产调度的精准性直接决定企业竞争力。深蓝易网MES系统通过智能化调度与全流程管控&#xff0c;帮助企业破解排产难题&#xff0c;实现资源高效协同与生产透明化管理&#xff0c;为制造企业打造柔性化、敏捷化的生产体系…

【深度学习】计算机视觉(18)——从应用到设计

文章目录 1 不同的注意力机制1.1 自注意力1.2 多头注意力1.3 交叉注意力1.3.1 基础1.3.2 进阶 1 不同的注意力机制 在学习的过程中&#xff0c;发现有很多计算注意力的方法&#xff0c;例如行/列注意力、交叉注意力等&#xff0c;如果对注意力机制本身不是特别实现&#xff0c…

洛谷 P1955 [NOI2015] 程序自动分析

【题目链接】 洛谷 P1955 [NOI2015] 程序自动分析 【题目考点】 1. 并查集 2. 离散化 【解题思路】 多组数据问题&#xff0c;对于每组数据&#xff0c;有多个 x i x j x_ix_j xi​xj​或 x i ≠ x j x_i \neq x_j xi​xj​的约束条件。 所有相等的变量构成一个集合&…

[Java] 输入输出方法+猜数字游戏

目录 1. 输入输出方法 1.1 输入方法 1.2 输出方法 2. 猜数字游戏 1. 输入输出方法 Java中输入和输出是属于Scanner类里面的方法&#xff0c;如果要使用这两种方法需要引用Scanner类。 import java.util.Scanner; java.util 是Java里面的一个包&#xff0c;里面包含一些工…

zst-2001 上午题-历年真题 UML(13个内容)

UML基础 UML - 第1题 ad UML - 第2题 依赖是暂时使用对象&#xff0c;关联是长期连接 依赖&#xff1a;依夜情 关联&#xff1a;天长地久 组合&#xff1a;组一辈子乐队 聚合&#xff1a;好聚好散 bd UML - 第3题 adc UML - 第4题 bad UML - 第5题 d UML…

WebFlux vs WebMVC vs Servlet 对比

WebFlux vs WebMVC vs Servlet 技术对比 WebFlux、WebMVC 和 Servlet 是 Java Web 开发中三种不同的技术架构&#xff0c;它们在编程模型、并发模型和适用场景上有显著区别。以下是它们的核心对比&#xff1a; 核心区别总览 特性ServletSpring WebMVCSpring WebFlux编程模型…

htmlUnit和Selenium的区别以及使用BrowserMobProxy捕获网络请求

1. Selenium&#xff1a;浏览器自动化之王 核心定位&#xff1a; 跨平台、跨语言的浏览器操控框架&#xff0c;通过驱动真实浏览器实现像素级用户行为模拟。 技术架构&#xff1a; 核心特性&#xff1a; 支持所有主流浏览器&#xff08;含移动端模拟&#xff09; 精…

SSRF相关

SSRF(Server Side Request Forgery,服务器端请求伪造)&#xff0c;攻击者以服务器的身份发送一条构造好的请求给服务器所在地内网进行探测或攻击。 产生原理&#xff1a; 服务器端提供了能从其他服务器应用获取数据的功能&#xff0c;如从指定url获取网页内容、加载指定地址的图…

SaaS备份的必要性:厂商之外的数据保护策略

在当今数字化时代&#xff0c;企业对SaaS&#xff08;软件即服务&#xff09;应用的依赖程度不断攀升。SaaS应用为企业提供了便捷的生产力工具&#xff0c;然而&#xff0c;这也使得数据安全面临诸多挑战&#xff0c;如意外删除、勒索软件攻击以及供应商故障等。因此&#xff0…

【Python 基础语法】

Python 基础语法是编程的基石&#xff0c;以下从核心要素到实用技巧进行系统梳理&#xff1a; 一、代码结构规范 缩进规则 使用4个空格缩进&#xff08;PEP 8标准&#xff09;缩进定义代码块&#xff08;如函数、循环、条件语句&#xff09; def greet(name):if name: # 正确缩…

利用“Flower”实现联邦机器学习的实战指南

一个很尴尬的现状就是我们用于训练 AI 模型的数据快要用完了。所以我们在大量的使用合成数据&#xff01; 据估计&#xff0c;目前公开可用的高质量训练标记大约有 40 万亿到 90 万亿个&#xff0c;其中流行的 FineWeb 数据集包含 15 万亿个标记&#xff0c;仅限于英语。 作为…

自动化测试与功能测试详解

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 什么是自动化测试? 自动化测试是指利用软件测试工具自动实现全部或部分测试&#xff0c;它是软件测试的一个重要组成 部分&#xff0c;能完成许多手工测试无…

MySQL全量,增量备份与恢复

目录 一.MySQL数据库备份概述 1.数据备份的重要性 2.数据库备份类型 3.常见的备份方法 二&#xff1a;数据库完全备份操作 1.物理冷备份与恢复 2.mysqldump 备份与恢复 3.MySQL增量备份与恢复 3.1MySQL增量恢复 3.2MySQL备份案例 三&#xff1a;定制企业备份策略思路…

Ubuntu 安装 Nginx

Nginx 是一个高性能的 Web 服务器和反向代理服务器&#xff0c;同时也可以用作负载均衡器和 HTTP 缓存。 Nginx 的主要用途 用途说明Web服务器提供网页服务&#xff0c;处理用户的 HTTP 请求&#xff0c;返回 HTML、CSS、JS、图片等静态资源。反向代理服务器将用户请求转发到…

人工智能 机器学习期末考试题

自测试卷2 一、选择题 1&#xff0e;下面哪个属性不是NumPy中数组的属性&#xff08; &#xff09;。 A&#xff0e;ndim B&#xff0e;size C&#xff0e;shape D&#xff0e;add 2&#xff0e;一个简单的Series是由&#xff08; &#xff09;的数据组成的。 A&#xff0e;两…