Qt C++ TCP服务端响应多客户端通讯

news2024/11/24 12:09:21

本示例使用的设备:WIFI无线4G网络RFID云读卡器远程网络开关物流网阅读器TTS语音-淘宝网 (taobao.com)

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QMessageBox"
#include <QDebug>
#include <exception>
#include <QTcpServer>
#include <QTcpSocket>
#include <QObject>
#include <QTime>
#include <QTreeWidgetItem>
#include <QClipboard>

bool listening=false;
QTcpServer m_server;
QTcpSocket m_socket;

//获取本机所有网卡IP------------------------------------------------------------------------------------------------------
QStringList getAllIPAddresses() {
    QStringList ips;
    QList<QHostAddress> list = QNetworkInterface::allAddresses();
    for (int i = 0; i < list.size(); ++i) {
        QHostAddress address = list.at(i);
        // 检查是否为IPv4地址,并排除回环地址
        if (address.protocol() == QAbstractSocket::IPv4Protocol && address != QHostAddress::LocalHost) {
            ips << address.toString();
        }
    }
    return ips;
}

//获取系统现时间-------------------------------------------------------------------------------------------------------------
QString getsystime(){
    QTime time = QTime::currentTime();
    QString timeStr = time.toString("hh:mm:ss.zzz");
    return timeStr;
}

//获取系统日期时间-------------------------------------------------------------------------------------------------------------
QString getsysdatetime(){
    QDateTime currentDateTime = QDateTime::currentDateTime();
    QString dateTimeString = currentDateTime.toString("yy-MM-dd hh:mm:ss");
    return dateTimeString;
}

//QByteArray转16进制QString------------------------------------------------------------------------------------------------
QString ByteArrayToHexString(QByteArray data){
    QString ret(data.toHex().toUpper());
    int len = ret.length()/2;
    for(int i=1;i<len;i++)
    {
        ret.insert(2*i+i-1," ");
    }
    return ret;
}

//通讯报文显示-----------------------------------------------------------------------------------------------------
void MainWindow::listadditems(int ctr,QString listinfo){
    switch (ctr){
    case 0:
        if(ui->listWidget_report->count()>30){
            ui->listWidget_report->clear();
        }
        ui->listWidget_report->addItem(listinfo);
        ui->listWidget_report->setCurrentRow(ui->listWidget_report->count()-1);
        break;
    case 1:
        ui->listWidget_online->addItem(listinfo);
        ui->listWidget_online->setCurrentRow(ui->listWidget_online->count()-1);
    }
}


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->TEPort->setPlainText("39169");        //出厂默认39169端口
    ui->spinBox_dispdelay->setValue(20);
    ui->spinBox_swit->setValue(30);
    ui->spinBox_voice->setValue(8);
    ui->textEdit_disp->setText("欢迎您使用我们的网络读卡器!");
    ui->textEdit_tts->setText("感谢您的使用,您的支持是我们最大的动力!");

    QStringList ips = getAllIPAddresses();
    foreach (QString ip, ips) {
        ui->CBIP->addItem(ip);
    }
    if(ui->CBIP->count()<1){
        QMessageBox::information(NULL, "提示", "未搜索到本机的网卡,系统不能正常运行!");
        delete ui;
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}

//启动、关闭TCP服务-------------------------------------------------------------------------------------------------------
void MainWindow::initserver(){
    try{
        if(ui->pushButton_initserver->text()=="开启TCP服务"){
            QString ipstr=ui->CBIP->currentText();
            QHostAddress localeip(ipstr);
            quint16 port=ui->TEPort->toPlainText().toUInt();

            m_server = new QTcpServer(this);
            m_server->listen(localeip, port);
            connect(m_server, &QTcpServer::newConnection, this, &MainWindow::onNewConnection);

            listening=true;
            ui->pushButton_initserver->setText("停止");
            listadditems(0,getsystime()+" Tcp Server is listening...");
        }else{
            listening=false;
            m_server->close();
            ui->pushButton_initserver->setText("开启TCP服务");
            for(int i=0;i<tcpclientlist.count();i++){
                tcpclientlist.at(i)->close();
                //tcpclientlist.remove(i);
                ui->listWidget_online->takeItem(i);
            }
            tcpclientlist.clear();
            listadditems(0,getsystime()+" Tcp Server is close! ");
        }
    }
    catch(_exception)
    {
        listening=false;
        ui->pushButton_initserver->setText("开启TCP服务");
    }
}

//侦听到有新的TCP客户端接入服务--------------------------------------------------------------------------------------------
void MainWindow::onNewConnection()
{
    m_socket = m_server->nextPendingConnection();
    tcpclientlist.append(m_socket);

    QString RemoIp=m_socket->peerAddress().toString();
    QString RemoPort=QString::number( m_socket->peerPort());
    listadditems(1,RemoIp+":"+RemoPort);
    listadditems(0,getsystime()+" NewConn "+RemoIp+":"+RemoPort);

    connect(m_socket, &QTcpSocket::readyRead, this, &MainWindow::onReadyRead);
    connect(m_socket, &QTcpSocket::disconnected, this, &MainWindow::onClientDisconnected);
    connect(m_socket, &QTcpSocket::connected, this, &MainWindow::onConnected);
//  connect(m_socket, &QTcpSocket::stateChanged, this, &MainWindow::onStateChanged);

}


//接收到TCP客户端传送来来的数据-------------------------------------------------------------------------------------------
void MainWindow::onReadyRead()
{
    QByteArray buffer;
    for(int row=0;row<tcpclientlist.count();row++){
        m_socket=tcpclientlist.at(row);
        buffer = m_socket->readAll();
        if(buffer.length()!=0){
            QString RemoIp=m_socket->peerAddress().toString();
            QString RemoPort=QString::number( m_socket->peerPort());
            listadditems(0,getsystime()+" Receive: "+RemoIp+":"+RemoPort+"    "+ByteArrayToHexString(buffer));

            unsigned char databuff[buffer.length()];
            std::copy(buffer.begin(), buffer.end(), databuff);

            switch (databuff[0]){
            case 0xc1:
            case 0xcf:
                 Analyze_c1_cf(row,databuff,buffer.length());          //解析读取IC卡卡号
                 break;

            case 0xd1:
            case 0xdf:
                 Analyze_d1_df(row,databuff,buffer.length());          //解析读取ID卡卡号
                 break;

            default:
                break;
            }
        }
    }
}


//侦测到TCP客户端断开连接---------------------------------------------------------------------------------------------
void MainWindow::onClientDisconnected()
{
    QString RemoIp=m_socket->peerAddress().toString();
    quint16 RemoPort= m_socket->peerPort();
    for(int i=0;i<tcpclientlist.count();i++){
        if(tcpclientlist.at(i)->peerAddress().toString()==RemoIp && tcpclientlist.at(i)->peerPort()==RemoPort){
            tcpclientlist.remove(i);
            ui->listWidget_online->takeItem(i);
            listadditems(0,getsystime()+" Disconn: "+RemoIp+":"+QString::number(RemoPort));
        }
    }
}


void MainWindow::onConnected()
{
    QString RemoIp=m_socket->peerAddress().toString();
    QString RemoPort=QString::number( m_socket->peerPort());
}

//void MainWindow::onStateChanged(QAbstractsocket::SocketState socketstate){
//    switch (socketstate){
//    case QAbstractSocket::UnconnectedState:ui->labConnectState->setText("Unconnectedstate");break;
//    case QAbstractSocket::HostLookupState:ui->labConnectState->setText("HostLookupstate");break;
//    case QAbstractSocket::ConnectedState:ui->labConnectState->setText("connectedstate");break;
//    case QAbstractSocket::ConnectingState:ui->labConnectState->setText("connectingstate");break;
//    case QAbstractSocket::BoundState: ui->labConnectState->setText("Boundstate");break;
//    case QAbstractSocket::ClosingState:ui->labConnectState->setText("closingstate");break;
//    case QAbstractSocket::ListeningState:ui->labConnectState->setText("listeningstate");break;
//    }
//}


//解析读取IC卡卡号-------------------------------------------------------------------------------------------------------------------
void MainWindow::Analyze_c1_cf(int socketid,unsigned char databuff[], qint64 buflen)
{
    QString IPAddress=QString::asprintf("%d", databuff[1])+"."+QString::asprintf("%d", databuff[2])+"."+QString::asprintf("%d", databuff[3])+"."+QString::asprintf("%d", databuff[4]); //设备IP地址,广域网上使用,一般不对此IP回应,而是对数据流的 ip及端口 回应
    QString DeviceNumber=QString::asprintf("%05d",databuff[5]+databuff[6]*256);   //设备自编机号
    QString FrameNumber=QString::asprintf("%05d",databuff[7]+databuff[8]*256);    //数据包号
    int cardnolen=databuff[9];

    QString CardnoHexZ="";          //16进制卡号正码
    QString CardnoHexF="";          //16进制卡号反码
    for (int i=0;i<cardnolen;i++){
        CardnoHexZ=CardnoHexZ+QString::asprintf("%02X", databuff[10+i]);
        if(i<4){CardnoHexF=CardnoHexF+QString::asprintf("%02X", databuff[9+cardnolen-i]);}   //只取4个字节计算8H10D反码
    }

    QString SerialNumber="";        //设备全球唯一硬件序号
    for (int i=10+cardnolen;i<buflen;i++){
        SerialNumber=SerialNumber+QString::asprintf("%02X", databuff[i]);
    }

    bool status;
    QString Cardno8H10D=QString::asprintf("%010u",CardnoHexF.toUInt(&status,16));  //转8H10D反码卡号

    QString  DispInf;
    if (databuff[0]==0xc1){DispInf="读取IC卡号,";}else{DispInf="IC卡离开读卡器,";}
    DispInf=DispInf+"设备IP:"+IPAddress+",机号:"+DeviceNumber+",数据包号:"+FrameNumber+",16进制卡号:"+CardnoHexZ+",转8H10D反码:"+Cardno8H10D+",设备全球唯一序号:"+SerialNumber;
    ui->plainTextEdit_msg->setPlainText(DispInf);

    if(ui->checkBox_Resp->isChecked()){Respondinfo(socketid,getsysdatetime()+"卡号:"+Cardno8H10D);}  //回应驱动设备显示+蜂鸣响声
}

//解析读取ID卡卡号-------------------------------------------------------------------------------------------------------------------
void MainWindow::Analyze_d1_df(int socketid,unsigned char databuff[], qint64 buflen)
{
    QString IPAddress=QString::asprintf("%d", databuff[1])+"."+QString::asprintf("%d", databuff[2])+"."+QString::asprintf("%d", databuff[3])+"."+QString::asprintf("%d", databuff[4]); //设备IP地址,广域网上使用,一般不对此IP回应,而是对数据流的 ip及端口 回应
    QString DeviceNumber=QString::asprintf("%05d",databuff[5]+databuff[6]*256);   //设备自编机号
    QString FrameNumber=QString::asprintf("%05d",databuff[7]+databuff[8]*256);    //数据包号

    QString CardnoHexZ="";          //16进制卡号正码
    QString CardnoHexF="";          //16进制卡号反码
    for (int i=0;i<5;i++){
        CardnoHexZ=CardnoHexZ+QString::asprintf("%02X", databuff[9+i]);
        if(i<4){CardnoHexF=CardnoHexF+QString::asprintf("%02X", databuff[9+3-i]);}   //只取4个字节计算8H10D反码
    }

    QString SerialNumber="";        //设备全球唯一硬件序号
    for (int i=9+5;i<buflen;i++){
        SerialNumber=SerialNumber+QString::asprintf("%02X", databuff[i]);
    }

    bool status;
    QString Cardno8H10D=QString::asprintf("%010u",CardnoHexF.toUInt(&status,16));  //转8H10D反码卡号

    QString  DispInf;
    if (databuff[0]==0xd1){DispInf="读取ID卡号,";}else{DispInf="ID卡离开读卡器,";}
    DispInf=DispInf+"设备IP:"+IPAddress+",机号:"+DeviceNumber+",数据包号:"+FrameNumber+",16进制卡号:"+CardnoHexZ+",转8H10D反码:"+Cardno8H10D+",设备全球唯一序号:"+SerialNumber;
                                                                                                                                                                          ui->plainTextEdit_msg->setPlainText(DispInf);

    if(ui->checkBox_Resp->isChecked()){Respondinfo(socketid,getsysdatetime()+"卡号:"+Cardno8H10D);}  //回应驱动设备显示+蜂鸣响声
}


void MainWindow::on_btnClose_clicked()
{
    m_server->close();
}


//向指定的客户端发送数据--------------------------------------------------------------------------------------------------------------
void MainWindow::SendBufToSockID(int socketid,QByteArray rbuffer){
    m_socket=tcpclientlist.at(socketid);
    m_socket->write(rbuffer);

    QString RemoIp=m_socket->peerAddress().toString();
    QString RemoPort=QString::number( m_socket->peerPort());
    QString SendHex=getsystime()+" Send To: "+(RemoIp+":"+RemoPort+"             ").mid(0,22);
    SendHex=SendHex+ByteArrayToHexString(rbuffer);
    listadditems(0,SendHex);
}


void MainWindow::on_pushButton_initserver_clicked()
{
    initserver();
}


//驱动读卡器蜂鸣响声-----------------------------------------------------------------------
void MainWindow::on_btnSendbeep_clicked()
{
    QListWidgetItem *item = ui->listWidget_online->currentItem();
    int row = ui->listWidget_online->row(item);
    if(row<0){
        QMessageBox::critical(this, "警告", "请选择一台在线设备再执行此功能!", QMessageBox::Ok);
    }else{
        QByteArray sendData;
        sendData.append(0x96);                             //功能码
        quint16 devno=0;
        sendData.append(devno % 256);                      //机号低位
        sendData.append(devno / 256);                      //机号高位,高低位都为0表示任意机号
        sendData.append(ui->CBbeep->currentIndex());       //蜂鸣响声代码
        SendBufToSockID(row,sendData);
    }
}

//驱动读卡器开启继电器-----------------------------------------------------------------------
void MainWindow::on_btnswitchon_clicked()
{
    QListWidgetItem *item = ui->listWidget_online->currentItem();
    int row = ui->listWidget_online->row(item);
    if(row<0){
        QMessageBox::critical(this, "警告", "请选择一台在线设备再执行此功能!", QMessageBox::Ok);
    }else{
        QByteArray sendData;
        sendData.append(0x78);                             //功能码
        quint16 devno=0;
        sendData.append(devno % 256);                      //机号低位
        sendData.append(devno / 256);                      //机号高位,高低位都为0表示任意机号
        QString swithno="F"+QString::asprintf("%d",ui->CBSwitch->currentIndex());
        bool status;
        sendData.append(swithno.toUInt(&status,16));       //选择继电器
        quint16 deltime=ui->spinBox_swit->value();
        sendData.append(deltime % 256);                    //开启延时低位
        sendData.append(deltime / 256);                    //开启延时高位
        SendBufToSockID(row,sendData);
    }
}

//驱动读卡器关闭已开启的继电器-----------------------------------------------------------------
void MainWindow::on_btnswitchoff_clicked()
{
    QListWidgetItem *item = ui->listWidget_online->currentItem();
    int row = ui->listWidget_online->row(item);
    if(row<0){
        QMessageBox::critical(this, "警告", "请选择一台在线设备再执行此功能!", QMessageBox::Ok);
    }else{
        QByteArray sendData;
        sendData.append(0x78);                             //功能码
        quint16 devno=0;
        sendData.append(devno % 256);                      //机号低位
        sendData.append(devno / 256);                      //机号高位,高低位都为0表示任意机号
        QString swithno="E"+QString::asprintf("%d",ui->CBSwitch->currentIndex());
        bool status;
        sendData.append(swithno.toUInt(&status,16));       //选择继电器
        quint16 deltime=ui->spinBox_swit->value();
        sendData.append(deltime % 256);                    //开启延时低位
        sendData.append(deltime / 256);                    //开启延时高位
        SendBufToSockID(row,sendData);
    }
}

//驱动读卡器蜂鸣响声并显示文字---------------------------------------------------------------------
void MainWindow::on_btnDispbeep_clicked()
{
    QListWidgetItem *item = ui->listWidget_online->currentItem();
    int row = ui->listWidget_online->row(item);
    if(row<0){
        QMessageBox::critical(this, "警告", "请选择一台在线设备再执行此功能!", QMessageBox::Ok);
    }else{
        QByteArray sendData;
        sendData.append(0x5A);                             //功能码
        quint16 devno=0;
        sendData.append(devno % 256);                      //机号低位
        sendData.append(devno / 256);                      //机号高位,高低位都为0表示任意机号
        sendData.append(ui->CBbeep->currentIndex());       //蜂鸣响声代码,255表示不响声
        sendData.append(ui->spinBox_dispdelay->value());   //文字显示时长,
        QString dispstr=ui->textEdit_disp->toPlainText()+"                                  ";  //加空格是为了确保满屏34位显示
        QByteArray Dispbyte=dispstr.toLocal8Bit();
        for(int i=0;i<34;i++){
            sendData.append(Dispbyte[i]);
        }
        SendBufToSockID(row,sendData);
    }
}

//驱动读卡器蜂鸣响声+显示文字+播报TTS语音+开启继电器开关
void MainWindow::on_btndispbeeptts_clicked()
{
    QListWidgetItem *item = ui->listWidget_online->currentItem();
    int row = ui->listWidget_online->row(item);
    if(row<0){
        QMessageBox::critical(this, "警告", "请选择一台在线设备再执行此功能!", QMessageBox::Ok);
    }else{
        if(ui->spinBox_voice->value()>16){ui->spinBox_voice->setValue(16);} //tts最大语音取值16
        QString strls="[v"+QString::asprintf("%d",ui->spinBox_voice->value())+"]";
        strls=strls+ui->textEdit_tts->toPlainText().trimmed();
        QByteArray SpeakArr=strls.toLocal8Bit();         //TS语音转换为Ansi码
        quint8 speakbytes=SpeakArr.size();
        quint8 dispbytes=34;                //双行显示屏显示长度34,四行屏显示长度72

        QByteArray sendData;
        sendData.append(0x5c);                             //功能码
        quint16 devno=0;
        sendData.append(devno % 256);                      //机号低位
        sendData.append(devno / 256);                      //机号高位,高低位都为0表示所有机
        sendData.append(ui->CBbeep->currentIndex());       //蜂鸣响声代码,取值255表示不响

        QString swithno="F"+QString::asprintf("%d",ui->CBSwitch->currentIndex());
        bool status;
        sendData.append(swithno.toUInt(&status,16));       //选择继电器
        quint16 deltime=ui->spinBox_swit->value();
        sendData.append(deltime % 256);                    //延时低位
        sendData.append(deltime / 256);                    //延时高位

        sendData.append(ui->spinBox_dispdelay->value());   //文字显示时长,
        quint8 begindisp =0;                               //在显示屏中的哪个位置开始显示,一般取0
        sendData.append(begindisp);
        sendData.append(dispbytes);                        //显示文字长度
        sendData.append(speakbytes);                       //tts语音长茺

        QString dispstr=ui->textEdit_disp->toPlainText()+"                                  ";  //加空格是为了确保满屏34位显示
        QByteArray Dispbyte=dispstr.toLocal8Bit();
        for(int i=0;i<dispbytes;i++){
            sendData.append(Dispbyte[i]);       //显示信息
        }
        for(int i=0;i<speakbytes;i++){
            sendData.append(SpeakArr[i]);       //TTS语音信息
        }

        sendData.append(0x55);      //防干扰后缀
        sendData.append(0xaa);
        sendData.append(0x66);
        sendData.append(0x99);
        SendBufToSockID(row,sendData);
    }
}

//接收到刷卡数据立即回应--------------------------------------------------------------------------
void MainWindow::Respondinfo(int socketid,QString Dispinf)
{
    QByteArray RespBuff;
    RespBuff.append(0x5A);                             //功能码
    quint16 devno=0;
    RespBuff.append(devno % 256);                      //机号低位
    RespBuff.append(devno / 256);                      //机号高位,高低位都为0表示任意机
    RespBuff.append(ui->CBbeep->currentIndex());       //蜂鸣响声代码,255表示不响声
    RespBuff.append(ui->spinBox_dispdelay->value());   //文字显示时长,
    QString dispstr=Dispinf+"                                  ";  //加空格是为了确保满屏34位显示
    QByteArray Dispbyte=dispstr.toLocal8Bit();
    for(int i=0;i<34;i++){
        RespBuff.append(Dispbyte[i]);
    }

    m_socket=tcpclientlist.at(socketid);
    m_socket->write(RespBuff);

    QString RemoIp=m_socket->peerAddress().toString();
    QString RemoPort=QString::number( m_socket->peerPort());
    QString SendHex=getsystime()+" Send To: "+(RemoIp+":"+RemoPort+"             ").mid(0,22);
    SendHex=SendHex+ByteArrayToHexString(RespBuff);
    listadditems(0,SendHex);
}


void MainWindow::on_btncopyreport_clicked()
{
    QString listinf;
    int row=ui->listWidget_report->count();
    if (row<1){
        return;
    }else{
        for (int i=0;i<row;i++){
            QListWidgetItem *item = ui->listWidget_report->item(i);
            listinf=listinf+item->text()+"\n";
        }
        QClipboard *clipboard = QApplication::clipboard();
        clipboard->setText(listinf);
        QMessageBox::information(this, "提示", "显示数据报文已拷贝到剪切板");
    }
}

源码下载 :https://download.csdn.net/download/zhangjin7422/89421064

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

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

相关文章

【春秋云镜】Faculty Evaluation System未授权任意文件上传漏洞(CVE-2023-33440)

因为该靶场没有Write up,索性自己搞一下&#xff0c;方便别人&#xff0c;快乐自己&#xff01; 漏洞概述&#xff1a; Sourcecodester Faculty Evaluation System v1.0 is vulnerable to arbitrary code execution via /eval/ajax.php?actionsave_user. 漏洞复现&#xff…

Halcon 多相机统一坐标系

小杨说事-基于Halcon的多相机坐标系统一原理个人理解_多相机标定统一坐标系-CSDN博客 一、概述 最近在搞多相机标定等的相关问题&#xff0c;对于很大的场景&#xff0c;单个相机的视野是不够的&#xff0c;就必须要统一到一个坐标系下&#xff0c;因此我也用了4个相机&#…

SpringBoot Vue Bootstrap 旅游管理系统

SpringBoot Vue 旅游管理系统源码&#xff0c;附带环境安装&#xff0c;运行说明 源码地址 开发环境 jdk1.8,mysql8,nodejs16,navicat,idea 使用技术springboot mybatis vue bootstrap 部分功能截图预览

数据合规怎么做?哪些机构可以做数据合规

企业将数据资源入表的工作是一项复杂而全面的任务 财务部门负责统计数据资源的成本、销售数据等信息,并确保数据资源的会计处理符合会计要求&#xff1b; 数据部门则负责统计数据成本来源、价值实现路径等信息&#xff1b; 法务部门需要确认数据的收集和使用遵循相关的合规要求…

算法分析与设计期末考试复习

重点内容&#xff1a; 绪论&#xff1a; 简单的递推方程求解 1.19(1)(2) 、 教材例题 多个函数按照阶的大小排序 1.18 分治法&#xff1a; 分治法解决芯片测试问题 计算a^n的复杂度为logn的算法&#xff08;快速幂&#xff09; 分治法解决平面最近点对问…

基于遗传优化算法的风力机位置布局matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于遗传优化算法的风力机位置布局matlab仿真&#xff0c;风力机位置布局优化是风能转换系统设计中的一个重要环节&#xff0c;旨在最大化风场的整体发电效率。仿…

数字芯片——时钟与复位

关于此次章节我想要探讨的问题是门控时钟的处理&#xff08;Clock Gating Methodology&#xff09;和时钟复位策略。在低功耗设计中&#xff0c;门控时钟是结构最简洁&#xff0c;最容易实现的电路结构。如上期所讲的&#xff0c;一个控制信号和时钟逻辑与在一起输出的信号作用…

redis设计与实现(四)服务器中的数据库

服务器中的数据库 Redis服务器将所有数据库都保存在服务器状态server.h结构的db数组中&#xff0c;db数组的每个项都是一个redis.h/redisDb结构&#xff0c;每个redisDb结构代表一个数据库。 在初始化服务器时&#xff0c;程序会根据服务器状态的dbnum属性来决定应该创建多少…

产品人生(12):从“产品生命周期管理”看如何做“职业规划”

产品生命周期管理是产品人常接触的一个概念&#xff0c;它是一种全面管理产品从概念构想、设计开发、生产制造、市场推广、销售使用&#xff0c;直至最终退役的全生命周期过程的方法论和一系列业务流程。下面我们来简单介绍下产品生命周期管理&#xff1a; 概念阶段&#xff1a…

C++ | Leetcode C++题解之第145题二叉树的后序遍历

题目&#xff1a; 题解&#xff1a; class Solution { public:void addPath(vector<int> &vec, TreeNode *node) {int count 0;while (node ! nullptr) {count;vec.emplace_back(node->val);node node->right;}reverse(vec.end() - count, vec.end());}vect…

【全开源】多平台租房系统源码(Fastadmin+ThinkPHP+Uniapp)

&#x1f3e0;多平台租房系统&#xff1a;一站式租房新体验&#x1f50d; &#x1f310;一、引言&#xff1a;租房市场的变革 在快节奏的现代生活中&#xff0c;租房已成为许多人解决居住问题的首选。然而&#xff0c;传统的租房方式往往繁琐且效率低下。随着互联网的飞速发展…

macOS Sequoia 将 Mac 生产力与智能化提升至全新高度 (macOS 15 ISO、IPSW、PKG 下载)

macOS Sequoia 将 Mac 生产力与智能化提升至全新高度 (macOS 15 ISO、IPSW、PKG 下载) iPhone 镜像、Safari 浏览器重大更新、备受瞩目的游戏和 Apple Intelligence 等众多全新功能令 Mac 使用体验再升级 请访问原文链接&#xff1a;https://sysin.org/blog/macOS-Sequoia/&a…

全方位·多层次·智能化,漫途水库大坝安全监测方案

党的十九届五中全会提出&#xff0c;到2025年前&#xff0c;完成新出现病险水库的除险加固&#xff0c;配套完善重点小型水库雨水情和安全监测设施&#xff0c;实现水库安全鉴定和除险加固常态化。 加快推进小型水库除险加固。加快构建气象卫星和测雨雷达、雨量站、水文站组成…

GIS之arcgis系列10:arcpy实现批量掩膜提取

按掩膜提取 (Spatial Analyst) 提取掩膜所定义区域内的相应栅格像元。 OutRas ExtractByMask(InRas1, InMsk1, "INSIDE") 使用情况 输入栅格中的其他属性&#xff08;若有的话&#xff09;将按照原样添加到输出栅格属性表。 根据所记录的属性&#xff0c;某些属性…

Golang | Leetcode Golang题解之第145题二叉树的后序遍历

题目&#xff1a; 题解&#xff1a; func reverse(a []int) {for i, n : 0, len(a); i < n/2; i {a[i], a[n-1-i] a[n-1-i], a[i]} }func postorderTraversal(root *TreeNode) (res []int) {addPath : func(node *TreeNode) {resSize : len(res)for ; node ! nil; node n…

STM32—U8g2图形库练习

一、新建CubeMX工程 1.照例将RCC配置为外部高速晶振&#xff08;精度更高&#xff09;——HSE&#xff1b;将SYS的Debug设置成Serial Wire&#xff08;否则可能导致芯片自锁)&#xff1b; 2.配置I2C2作为OLED的通讯方式。 3.TIM1配置&#xff1a;U8g2图形库需要us级延迟推动&…

uniapp地图选择位置

直接上代码 通过一个点击事件调用官方api即可调用 点击调用成功后显示如下 然后选择自己所需要的位置即可

Mssql数据注入

1.查询用户创建的数据表 select id,name from sysobjects where xtypeu ; 2.查询用户创建数据表的具体列名 select * from syscolumns where id 上一步获取的id值; 3.查询具体内容 select id,字段名 from 数据表名&#xff1b; 4.数据库名 db_name() 5.用户登录名 su…

使用Ollama简单部署本地Qwen2

Ollama 是一个开源的、本地运行的 AI 聊天模型&#xff0c;允许在自己的设备上运行 LLM&#xff0c;无需依赖云服务。它支持多种 LLM。目前Ollama library已经支持Qwen2&#xff0c;可以直接使用。 首先安装ollama&#xff0c; 访问官网 下载 ollama 对应版本 Download Ollama…

数字时代网络安全即服务的兴起

在日益数字化的世界里&#xff0c;威胁形势不断演变&#xff0c;网络攻击变得越来越复杂和频繁。当组织努力保护敏感数据并保持运营完整性时&#xff0c;传统的网络安全措施往往不够。 这为更具动态性和可扩展性的解决方案铺平了道路&#xff1a;网络安全即服务 (CSaaS)。网络…