QT--网络篇

news2024/11/15 11:04:42
  1. 如果QT头文件找不到QTcpSocket、QTcpSocket、QTcpServer、QtNetwork ,那么可能是pro文件中缺少QT += network这行代码
    在这里插入图片描述

客户端QTcpSocket

  1. void QTcpSocket::connectToHost( QString servip, quint16 port );
  • connectToHost 函数会尝试与指定的服务器建立 TCP 连接。如果连接成功,将会触发 connected 信号,如果连接失败,将会触发 errorOccurred 信号。属于QTcpSocket类
  • QString servip:这是服务器的 IP 地址或主机名。QString 是 Qt 提供的一个字符串类,用于处理文本字符串。
  • quint16 port:这是服务器的端口号。quint16 是 Qt 提供的一个无符号 16 位整数类型,通常用于表示端口号。
    代码举例
QTcpSocket *socket = new QTcpSocket;

// 连接到服务器,假设服务器的 IP 地址是 "192.168.1.100" 端口号是 12345
socket->connectToHost("192.168.1.100", 12345);

// 连接成功时,触发的槽函数
connect(socket, SIGNAL(connected()), this, SLOT(onConnected()));

// 连接失败时,触发的槽函数
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));

  • toUShort() 是 Qt 中 QString 类的成员函数,用于将字符串转换为 unsigned short(即 quint16)类型的整数。其作用是将一个表示数字的字符串转换为对应的无符号 16 位整数。这适合于从lineEdit中获取端口号。
  1. QTcpSocket的信号有
    - connected(),当套接字成功连接到目标主机时发出的信号。
    - disconnected(),当套接字与目标主机断开连接时发出的信号。
    - readyRead(),当套接字有新的数据可供读取时发出的信号。
// 假设 ptCliSocket 是一个 QTcpSocket 对象,在构造函数或其他地方已经创建和初始化好了。

// 连接 readyRead 信号到 ptCliSocketReadyReadSlotFun 槽函数,即当 ptCliSocket 有可读数据时调用 ptCliSocketReadyReadSlotFun 函数。
connect(ptCliSocket, SIGNAL(readyRead()), this, SLOT(ptCliSocketReadyReadSlotFun()));

void Widget::ptCliSocketReadyReadSlotFun()
{
    char buf[512] = {0}; // 创建一个 512 字节大小的字符数组,用于存储接收到的数据。

    int ret = ptCliSocket->read(buf, sizeof(buf)); // 从 ptCliSocket 中读取数据到 buf 中,最多读取 sizeof(buf) 字节的数据。
    if (ret < 0) { // 如果读取失败(返回值小于 0),显示接收错误信息到界面上的 labelTips,并返回。
        ui->labelTips->setText("recv err");
        return;
    }

    // 将读取到的数据显示在界面上的 textEdit 控件中。
    ui->textEdit->setText(buf);
}

-------------------------------------------------------------------------
//上面是read读出,以下是write写入
在 QTcpSocket 类中,调用 write 方法写入数据并没有对应的信号。写入数据是一个操作,它不会触发信号。信号通常用于通知接收到新数据(readyRead 信号)或连接状态变化等事件,而不是在发送数据时触发的。

当你调用 QTcpSocket 的 write 方法写入数据时,它是一个阻塞操作,意味着程序会等待数据完全写入或发生错误才会继续执行后续代码。如果需要了解写入操作的结果,你可以根据返回值来判断是否写入成功,而不需要依赖信号来通知。

QTcpSocket *socket = new QTcpSocket;

// 假设已连接到服务器

char data[] = "Hello, server!"; // 准备要发送的数据,这里使用 C 风格的字符串
quint64 size = strlen(data);   // 获取要发送数据的长度

qint64 bytesWritten = socket->write(data, size); // 向服务器发送数据,并记录实际写入的字节数
if (bytesWritten == -1) { // 如果写入操作返回 -1,表示出现错误
    qDebug() << "Error writing to socket:" << socket->errorString(); // 输出错误信息
} else { // 写入成功的情况
    qDebug() << "Successfully wrote" << bytesWritten << "bytes to socket."; // 输出成功写入的字节数
}




  1. 关于write和read
  • quint64 QIODevice::write(char *data, quint64 size); 向服务器发送消息: 返回值-和普通的write保持一致
  • quint64 QIODevice::read (char *data, quint64 size); 返回值和以前一致,0表示没有数据,注意,gui进程如果使用read,一定要确保有数据才去读;所以一般绑定readyread()信号
  1. close
  • 关闭连接:这是 QIODevice 类的成员函数,用于关闭设备(例如文件、套接字等)。在网络编程中,特别是在 QTcpSocket 类中,调用 close() 方法会关闭当前的网络连接。
  • :Qt 中的大多数函数都是非阻塞的。这意味着调用 close() 方法不会立即阻塞程序的执行,而是将关闭操作放入事件循环中处理,使得程序可以继续执行后续代码或响应其他事件。具体来说,在网络编程中,当调用 close() 方法时,它会发送关闭请求,并立即返回,而实际的关闭操作会在稍后异步完成。
  1. 一些小函数交互类
  • toStdString()
    • toStdString() 是 Qt 中的一个成员函数,用于将 Qt 的字符串类型转换为标准的 C++ 字符串 std::string。在实际开发中,这个函数经常用于将 Qt 的字符串类型(如 QString)转换为标准库 std::string,以便在 Qt 和标准 C++ 代码之间进行数据交换或处理。
  • c_str()
    • c_str() 是 C++ 标准库中用于获取字符串的 C 风格(以 null 结尾的字符数组)表示的成员函数。在 Qt 编程中,如果你有一个 QString 或 QByteArray,你可以使用 c_str() 方法来获取其对应的 C 风格字符串指针,即 const char * 类型的指针。
代码举例
#include <QString>
#include <QByteArray>
#include <iostream>

int main() {
    QString qtString = "Hello, Qt!";
    QByteArray byteArray = "Hello, QByteArray!";
    
    // 使用 c_str() 获取 C 风格字符串,并输出
    const char *cString1 = qtString.toStdString().c_str();
    const char *cString2 = byteArray.toStdString().c_str();
    
    // 输出 C 风格字符串
    std::cout << "C string (from QString): " << cString1 << std::endl;
    std::cout << "C string (from QByteArray): " << cString2 << std::endl;
    
    // 使用 toStdString() 直接转换为 std::string,然后输出
    std::string stdString1 = qtString.toStdString();
    std::string stdString2 = byteArray.toStdString();
    
    std::cout << "std::string (from QString): " << stdString1 << std::endl;
    std::cout << "std::string (from QByteArray): " << stdString2 << std::endl;
    
    return 0;
}
-------------------------------------------------------------------------------
例子2 

void Widget::btnSendClickedSlotFun()
{
    QString str = ui->leSendContext->text();
    std::string sstr = str.toStdString();
    const char *pch = sstr.c_str();

    int ret = ptCliSocket->write(pch,sstr.length());
    if(ret <0){
        ui->labelTips->setText("send err!!!");
        return;
    }
    return;
}

服务器QTcpServer

  • QTcpServer 是 Qt 网络模块中的一个类,用于创建一个 TCP 服务器,可以监听指定的地址和端口,接受客户端的连接请求。
1.QTcpServer 的信号
  • newConnection(),当有新的连接到达时,会触发这个信号。可以连接到一个槽函数,用于处理新的 QTcpSocket 连接。
connect(server,SIGNAL(newConnection()),this,SLOT(serverNewConnectionSlot()  ));
  • acceptError(QAbstractSocket::SocketError),这个信号在服务器在接受连接时发生错误时发出。可以通过连接到一个槽函数,来处理这些错误。(一般不用)。
connect(server, SIGNAL(acceptError(QAbstractSocket::SocketError)), 
                this, SLOT(onAcceptError(QAbstractSocket::SocketError)));
2. nextPendingConnection 下一个挂起连接
  • nextPendingConnection 是 QTcpServer 类的一个成员函数,其作用是返回下一个挂起的连接请求,并生成一个与该连接相关的 QTcpSocket 对象。这个函数通常在处理 newConnection 信号的槽函数中调用,用于获取新的客户端连接。
// 接受新的连接
        QTcpSocket *socket = server->nextPendingConnection();
  • 如果没有挂起的连接请求,则返回 nullptr。
  • QTcpSocket::readyRead 信号: 当有数据可读时触发,用于读取客户端发送的数据。
  • QTcpSocket::disconnected 信号: 当连接断开时触发,用于清理资源。
  • tips:由于QTcpServer 默认支持多个并发连接。可以在同一时间与多个客户端进行通信。你可以通过处理 newConnection 信号来接受多个客户端连接,并使用 QTcpSocket 对象与每个客户端进行独立的通信。
  • 在widget.h中定义**QList<QTcpSocket*> sockets;*是在 Qt 中声明一个名为sockets的列表,该列表包含 QTcpSocket 类型的指针。这意味着sockets是一个可以存储多个 QTcpSocket 指针的容器,方便管理和操作多个客户端连接。比如使用sockets.append(newSocket);//将新的Socket指针存入数组中
3.判断是哪个客户端发来了信息
  • 对socket进行read操作即可,判断读取是否非0,非0即是该socket发来的信息
void Widget::pCliSockReadyReadSlot()
{
    char buf[512] = {0}; // 用于存储从客户端读取的数据的缓冲区,初始清空

    // 遍历所有已连接的客户端 socket
    for(int i = 0; i < sockets.length(); i++){
        QTcpSocket *p = sockets.at(i); // 获取第 i 个客户端 socket

        int ret = p->read(buf, sizeof(buf)); // 从客户端 socket 中读取数据到 buf 中,返回值 ret 表示实际读取的字节数。


        if(ret == 0){
            continue; // 如果未读取到数据,继续下一个客户端 socket 的处理
        }

        // 显示接收到的消息在界面的 textEdit 中
        ui->textEdit->setText(buf);

        char sendbuf[] = "hello client, Ur msg be got!";
        p->write(sendbuf, strlen(sendbuf)); // 向客户端发送响应消息
    }
}

4.判断是哪个客户端关闭了连接
  • state()
  • QTcpServer 类具有一个 state() 函数,用于获取当前 TCP 服务器的状态。这个函数返回一个枚举值 QAbstractSocket::SocketState,表示服务器当前的连接状态。这个状态对于管理和监控服务器的运行状态非常有用。
    有以下几种状态值
状态值含义
QAbstractSocket::UnconnectedState服务器处于未连接状态,即尚未开始监听任何客户端连接。
QAbstractSocket::HostLookupState服务器正在进行主机名查找,用于解析 IP 地址。
QAbstractSocket::ConnectingState服务器正在尝试与另一个设备建立连接。
QAbstractSocket::ConnectedState服务器已成功连接到另一个设备。
QAbstractSocket::BoundState服务器已绑定到本地地址和端口,等待连接请求。
QAbstractSocket::ClosingState服务器正在关闭连接,即将结束当前的连接。
QAbstractSocket::ListeningState服务器正在监听传入的连接请求。

一般用第一个判断是否断开连接

void Widget::pCliSockDisconnectionSlot()
{
    for(int i = 0; i < sockets.length(); i++){
        QTcpSocket *p = sockets.at(i); // 获取第 i 个客户端的 QTcpSocket 对象指针

        // 检查客户端的连接状态是否为未连接状态
        if(p->state() == QAbstractSocket::UnconnectedState){
            p->close(); // 如果客户端已经断开连接,关闭当前的 QTcpSocket 对象
            sockets.removeAt(i); // 从列表中移除已经断开连接的客户端 QTcpSocket 对象
            ui->textEdit->setText("found cli shutdown!"); // 在界面的 textEdit 中显示找到客户端断开连接的消息
        }
    }
}

5.如何启动服务器
  • listen(),listen() 函数是用于 QTcpServer 类的成员函数,用来开始监听指定地址和端口的连接请求。它的作用是启动服务器,使其能够接受来自客户端的连接。
bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)
参数
address:要监听的本地地址。默认为 QHostAddress::Any,表示监听所有可用的网络接口。
port:要监听的端口号。如果为 0,系统将分配一个随机的未使用端口。
返回值
true:如果成功开始监听指定的地址和端口。
false:如果不能开始监听,可能是由于地址或端口被占用或其他原因导致的失败。
  • 代码举例
void Widget::btnSetupClickedSlot()
{
    // 从界面的 lePort LineEdit 中获取端口号,并转换为 quint16 类型
    quint16 port = ui->lePort->text().toUShort();

    // 调用 ptTcpServ(QTcpServer 对象)的 listen 函数,开始监听任意本地地址和指定端口
    bool r = ptTcpServ->listen(QHostAddress::Any, port);

    // 检查 listen 函数返回值,r 为 false 表示服务器启动失败
    if(r == false){
        ui->textEdit->setText("serv setup failed!"); // 在界面的 textEdit 中显示服务器设置失败的消息
        return; // 退出函数
    }

    ui->textEdit->setText("serv setup success"); // 在界面的 textEdit 中显示服务器设置成功的消息
    // 服务器启动成功,等待客户端连接的信号处理
}

代码举例

服务器代码
//widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QTcpServer>
#include<QTcpSocket>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
public slots:
    void serverNewConnectedSlotFun();
    void socketReadyReadSlotFun();
    void socketDisconnectedSlotFun();
    void btnLinkClickedSlotFun();
    void socketBoxCurrentIndexChanged(int);



private:
    Ui::Widget *ui;
    QTcpServer *server;
    QList<QTcpSocket*> sockets;


};
#endif // WIDGET_H



//widget.cpp
#include "widget.h"
#include "ui_widget.h"

// Widget类的构造函数,初始化UI和QTcpServer对象,并设置连接信号槽
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this); // 设置UI
    server = new QTcpServer; // 创建QTcpServer对象
    connect(server, SIGNAL(newConnection()), this, SLOT(serverNewConnectedSlotFun())); // 连接新连接信号到槽函数
    ui->btnLink->setText("打开服务器"); // 设置按钮文本
    ui->linePort->setText("8888"); // 设置端口文本
    connect(ui->btnLink, SIGNAL(clicked()), this, SLOT(btnLinkClickedSlotFun())); // 连接按钮点击信号到槽函数
    connect(ui->socketsBox, SIGNAL(currentIndexChanged(int)), this, SLOT(socketBoxCurrentIndexChanged(int))); // 连接下拉框改变信号到槽函数
}

// Widget类的析构函数,释放UI资源
Widget::~Widget()
{
    delete ui; // 释放UI资源
}

// 当有新连接时,处理新连接的槽函数
void Widget::serverNewConnectedSlotFun()
{
    QTcpSocket *socket = server->nextPendingConnection(); // 获取新连接的socket
    connect(socket, SIGNAL(readyRead()), this, SLOT(socketReadyReadSlotFun())); // 连接数据可读信号到槽函数
    connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnectedSlotFun())); // 连接断开连接信号到槽函数

    sockets.append(socket); // 将新连接的socket添加到列表中
    QString str = QString("QTcpSocket(%1)").arg(reinterpret_cast<quintptr>(socket), 0, 16); // 获取socket的地址字符串
    ui->socketsBox->addItem(str); // 将地址字符串添加到下拉框
    ui->textEditRecv->setText("new connect"); // 设置文本编辑框的文本
}

// 当有数据可读时,处理读取数据的槽函数
void Widget::socketReadyReadSlotFun()
{
    char buf[512] = {0}; // 创建缓冲区
    QTcpSocket *p;
    for(int i = 0; i < sockets.length(); i++) { // 遍历所有socket
        p = sockets.at(i); // 获取当前socket
        int ret = p->read(buf, sizeof(buf)); // 读取数据到缓冲区
        if(ret == 0) {
            continue; // 如果没有数据读取,继续下一次循环
        }
        ui->textEditRecv->setText(buf); // 将读取的数据设置到文本编辑框
        char sendbuf[] = "hello client"; // 创建发送数据
        p->write(sendbuf, strlen(sendbuf)); // 发送数据到客户端
    }
}

// 当连接断开时,处理断开连接的槽函数
void Widget::socketDisconnectedSlotFun()
{
    for(int i = 0; i < sockets.length(); i++) { // 遍历所有socket
        QTcpSocket *p = sockets.at(i); // 获取当前socket
        if(p->state() == QAbstractSocket::UnconnectedState) { // 检查socket是否断开连接
            p->close(); // 关闭socket
            sockets.removeAt(i); // 从列表中移除socket
            ui->socketsBox->removeItem(i); // 从下拉框中移除项
            ui->textEditRecv->setText("found cli shutdown"); // 设置文本编辑框的文本
        }
    }
}

// 处理按钮点击事件的槽函数
void Widget::btnLinkClickedSlotFun()
{
    quint16 port = ui->linePort->text().toUShort(); // 获取端口号
    bool ret = server->listen(QHostAddress::Any, port); // 启动服务器监听
    if(ret == false) {
        ui->textEditRecv->setText("打开服务器失败"); // 如果监听失败,设置文本编辑框的文本
        return;
    }
    ui->textEditRecv->setText("打开服务器成功"); // 如果监听成功,设置文本编辑框的文本
}

// 处理下拉框当前索引改变事件的槽函数
void Widget::socketBoxCurrentIndexChanged(int i)
{
    QString send = ui->textEditSend->toPlainText(); // 获取发送数据
    const char *send1 = send.toStdString().c_str(); // 将QString转换为C字符串

    QString str = ui->socketsBox->itemText(i); // 获取下拉框当前选中的文本
    for(int i = 0; i < sockets.length(); i++) { // 遍历所有socket
        QTcpSocket* aimSocket = sockets.at(i); // 获取当前socket
        QString straim = QString("QTcpSocket(%1)").arg(reinterpret_cast<quintptr>(aimSocket), 0, 16); // 获取socket的地址字符串
        if(str == straim) { // 如果地址字符串匹配
            int ret = aimSocket->write(send1, strlen(send1)); // 发送数据到客户端
            if(ret < 0) {
                ui->label->setText("发送失败"); // 如果发送失败,设置标签的文本
            } else {
                ui->label->setText("发送成功"); // 如果发送成功,设置标签的文本
            }
        }
    }
}

客户端代码
//widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QTcpSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
public slots:
    void btnlinkClickedSlotFun();
    void socketClientConnectedSlotFun();
    void socketClientReadyReadSlotFun();
    void socketClientDisconnectedSlotFun();
    void btnSendClickedSlotFun();
private:
    Ui::Widget *ui;
    QTcpSocket *SocketClient;
};
#endif // WIDGET_H


//widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include<QDebug>

// Widget类的构造函数,初始化UI和QTcpSocket对象,并设置连接信号槽
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this); // 设置UI
    SocketClient = new QTcpSocket; // 创建QTcpSocket对象
    ui->btnlink->setText("connect"); // 设置连接按钮的文本
    connect(ui->btnlink, SIGNAL(clicked()), this, SLOT(btnlinkClickedSlotFun())); // 连接按钮点击信号到槽函数

    connect(SocketClient, SIGNAL(connected()), this, SLOT(socketClientConnectedSlotFun())); // 连接socket连接成功信号到槽函数
    connect(SocketClient, SIGNAL(readyRead()), this, SLOT(socketClientReadyReadSlotFun())); // 连接socket有数据可读信号到槽函数
    connect(SocketClient, SIGNAL(disconnected()), this, SLOT(socketClientDisconnectedSlotFun())); // 连接socket断开连接信号到槽函数

    ui->btnSend->setText("发送"); // 设置发送按钮的文本
    connect(ui->btnSend, SIGNAL(clicked()), this, SLOT(btnSendClickedSlotFun())); // 连接发送按钮点击信号到槽函数
    ui->lineIp->setText("192.168.124.137"); // 设置默认IP地址
    ui->linePort->setText("8888"); // 设置默认端口号
}

// Widget类的析构函数,释放UI资源
Widget::~Widget()
{
    delete ui; // 释放UI资源
}

// 处理连接按钮点击事件的槽函数
void Widget::btnlinkClickedSlotFun()
{
    if(ui->btnlink->text() == "connect") { // 如果按钮文本为"connect"
        QString Ip = ui->lineIp->text(); // 获取IP地址
        quint16 Port = ui->linePort->text().toUShort(); // 获取端口号
        SocketClient->connectToHost(Ip, Port); // 连接到服务器
    }
    else if(ui->btnlink->text() == "disconnect") // 如果按钮文本为"disconnect"
        SocketClient->close(); // 关闭连接
    else
        ui->labelTips->setText("connect error"); // 如果文本为其他值,显示错误信息
}

// 处理socket连接成功事件的槽函数
void Widget::socketClientConnectedSlotFun()
{
    ui->btnlink->setText("disconnect"); // 设置按钮文本为"disconnect"
    ui->labelTips->setText("Tips:connected success"); // 显示连接成功信息
}

// 处理socket有数据可读事件的槽函数
void Widget::socketClientReadyReadSlotFun()
{
    char buf[512] = {0}; // 创建缓冲区
    int ret = SocketClient->read(buf, sizeof(buf)); // 读取数据到缓冲区
    if(ret < 0) {
        ui->labelTips->setText("Tips:读取错误"); // 如果读取失败,显示错误信息
        return;
    }
    ui->textRecv->setText(buf); // 将读取的数据设置到文本框
}

// 处理socket断开连接事件的槽函数
void Widget::socketClientDisconnectedSlotFun()
{
    ui->btnlink->setText("connect"); // 设置按钮文本为"connect"
    ui->labelTips->setText("Tips:连接断开"); // 显示连接断开信息
}

// 处理发送按钮点击事件的槽函数
void Widget::btnSendClickedSlotFun()
{
    QString send = ui->lineSend->text(); // 获取发送数据
    const char *send1 = send.toStdString().c_str(); // 将QString转换为C字符串

    int ret = SocketClient->write(send1, strlen(send1)); // 发送数据到服务器
    if(ret < 0) {
        ui->labelTips->setText("Tips:发送失败"); // 如果发送失败,显示错误信息
        return;
    }
    return;
}


在这里插入图片描述

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

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

相关文章

代码随想录算法训练营第35天|LeetCode 01背包问题 二维、01背包问题 一维、416. 分割等和子集

1. LeetCode 01背包问题 二维 题目链接&#xff1a;https://kamacoder.com/problempage.php?pid1046 文章链接&#xff1a;https://programmercarl.com/背包理论基础01背包-1.html#算法公开课 视频链接&#xff1a;https://www.bilibili.com/video/BV1cg411g7Y6/ 思路&#xf…

【Vue】`v-if` 指令详解:条件渲染的高效实现

文章目录 一、v-if 指令概述二、v-if 的基本用法1. 基本用法2. 使用 v-else3. 使用 v-else-if 三、v-if 指令的高级用法1. 与 v-for 一起使用2. v-if 的性能优化 四、v-if 的常见应用场景1. 表单验证2. 弹窗控制 五、v-if 指令的注意事项 Vue.js 是一个用于构建用户界面的渐进式…

在 PostgreSQL 里如何实现数据的冷热数据分层存储的自动化策略调整?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 在 PostgreSQL 里如何实现数据的冷热数据分层存储的自动化策略调整 在 PostgreSQL 里如何实现数据的冷…

最新可用度盘不限速后台系统源码_去授权开心版

某宝同款度盘不限速后台系统源码&#xff0c;验证已被我去除&#xff0c;两个后端系统&#xff0c;账号和卡密系统 第一步安装宝塔&#xff0c;部署卡密系统&#xff0c;需要环境php7.4 把源码丢进去&#xff0c;设置php7.4&#xff0c;和伪静态为thinkphp直接访问安装就行 …

bootstrap中文文档官网

Bootstrap v3 中文文档 Bootstrap 是最受欢迎的 HTML、CSS 和 JavaScript 框架&#xff0c;用于开发响应式布局、移动设备优先的 WEB 项目。 | Bootstrap 中文网

PostgreSQL 中如何解决因大量并发删除和插入操作导致的索引抖动?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 PostgreSQL 中如何解决因大量并发删除和插入操作导致的索引抖动一、理解索引抖动二、索引抖动的影响三…

C语言:温度转换

1.题目&#xff1a;实现摄氏度&#xff08;Celsius&#xff09;和华氏度&#xff08;Fahrenheit&#xff09;之间的转换。 输入一个华氏温度&#xff0c;输出摄氏温度&#xff0c;结果保留两位小数。 2.思路&#xff1a;&#xff08;这是固定公式&#xff0c;其中 F 是华氏度&a…

DL/T645-2007_Part1(协议帧解析)

帧结构 起始字符68H地址域起始字符68H控制码C数据域长度L数据域校验和CS结束字符16H1Byte6Byte1Byte1Byte1ByteN Byte1Byte1Byte 地址域 地址域为6个字节的BCD码构成&#xff0c;当使用的地址码长度不足6字节&#xff0c;高位用0补足&#xff1b;当通信地址为99999999999H时…

自学 阿里巴巴Java开发手册最新版(嵩山版)

&#x1f534; 阿里巴巴Java开发手册最新版&#xff08;嵩山版&#xff09; 一、编程规约(一) 命名风格(二) 常量定义(三) 代码格式(四) OOP 规约(五) 日期时间(六) 集合处理(七) 并发处理(八) 控制语句(九) 注释规约(十) 前后端规范 二、异常日志(一) 错误码(二) 异常处理(三)…

【BUG】已解决:python setup.py bdist_wheel did not run successfully.

已解决&#xff1a;python setup.py bdist_wheel did not run successfully. 目录 已解决&#xff1a;python setup.py bdist_wheel did not run successfully. 【常见模块错误】 解决办法&#xff1a; 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主…

自动驾驶-预测概览

通过生成一条路径来预测一个物体的行为&#xff0c;在每一个时间段内&#xff0c;为每一辆汽车重新计算预测他们新生成的路径&#xff0c;这些预测路径为规划阶段做出决策提供了必要信息 预测路径有实时性的要求&#xff0c;预测模块能够学习新的行为。我们可以使用多源的数据…

NetSuite Saved Search迁移工具

我们需要在系统间迁移Saved Search&#xff0c;但是采用Copy To Account或者Bundle时&#xff0c;会有一些Translation不能迁移&#xff0c;或者很多莫名其妙的Dependency&#xff0c;导致迁移失败。因此&#xff0c;我们想另辟蹊径&#xff0c;借助代码完成Saved Search的迁移…

数据库事务隔离级别及底层原理详解

本文详细记录了数据库中事务的隔离级别及其定义&#xff0c;以及每个隔离级别下可能会遇到哪些问题及对应的解决方案和原理&#xff0c;以下内容结合为各大平台的知识点加自己的理解进行的总结&#xff0c;希望大家在读完以后能对事务有个全新的认识~~ 1. MySQL事务管理 自动…

Connecting weaviate with langflow across docker containers

题意&#xff1a;在Docker容器之间连接Weaviate与Langflow 问题背景&#xff1a; I am trying to build a local RAG application using Langflow. For my vectore store, I want to use a local Weaviate instance, hosted in a separate docker container on the same netwo…

使用dock构建基于lnmp的WrodPress

项目要求&#xff1a; 1.创建nginx容器环境 上传nginx.conf文件、上传阿里云镜像、上传html目录 2.准备mysql cd /opt mkdir mysql 上传my.conf文件、上传阿里云镜像、写好的Dockfile文件 3.准备php cd /opt mkdir php 上传所需文件&#xff1a; 构建各镜像&#xff1a; …

【艺术向】【素描创作记录】《如何为你的红颜知己创作一幅画像(之二)》

写在前面 之前分析过类似的创作过程&#xff0c;见博客【艺术向】【素描创作记录】《如何为你的红颜知己创作一幅画像》 本人业余时间修习素描多年&#xff0c;在此撰文记录《如何为你的红颜知己创作一幅画像&#xff08;之二&#xff09;》&#xff0c;博得对方好感&#xff…

JQuery+HTML+JavaScript:实现地图位置选取和地址模糊查询

本文详细讲解了如何使用 JQueryHTMLJavaScript 实现移动端页面中的地图位置选取功能。本文逐步展示了如何构建基本的地图页面&#xff0c;如何通过点击地图获取经纬度和地理信息&#xff0c;以及如何实现模糊查询地址并在地图上标注。最后&#xff0c;提供了完整的代码示例&…

【proteus经典实战】LCD滚动显示汉字

一、简介 Proteus是一款功能丰富的电子设计和仿真软件&#xff0c;它允许用户设计电路图、进行PCB布局&#xff0c;并在虚拟环境中测试电路功能。这款软件广泛应用于教育和产品原型设计&#xff0c;特别适合于快速原型制作和电路设计教育。Proteus的3D可视化功能使得设计更加直…

Elasticsearch ILM 热节点迁移至冷节点 IO 打满、影响读写解决方案探讨

1、实战问题 ILM&#xff08;索引生命周期管理&#xff09; 遇到热数据迁移至冷节点时造成 IO 打满影响读写的情况。 现在采取的方案是调整索引生命周期策略&#xff0c;定时的将Cold phase 开启/关闭。低峰开启&#xff0c;高峰关闭。 就是不知道这里面会有啥坑。 热节点&…

C++笔试强训7

文章目录 一、选择题1-5题6-10题 二、编程题题目一题目二 一、选择题 1-5题 基础知识&#xff0c;函数代码少&#xff0c;频繁调用的时候才适合定义内联函数。 故选C。 在C中&#xff0c;inline关键字是用来向编译器建议将函数体在每个调用点“内联展开”的。这意味着编译器会…