HTTP协议手写服务器

news2025/4/2 4:14:11

目录

一、请求的是Web根目录

二、GET方法通过URL传参

三、根据资源类型对应出Content-Type值

四、Http代码


项目完整源代码:Http · 周不才/cpp_linux study - 码云 - 开源中国

一、请求的是Web根目录

如果URL中请求的资源是Web根目录,则自动跳转到主页

例如QQ官网https://im.qq.com/,实际访问时会自动跳转到主页https://im.qq.com/index/

实现代码:

static const std::string homePage="index.html";//主页资源
//解析请求的资源路径path,如果请求的是web根目录
if(_path[_path.size()-1]=='/')
{
    _path+=homePage;
}

二、GET方法通过URL传参

GET方法和POST方法都可以通过表单等方式向服务器传递数据

GET方法会将表单的数据存放到URL中,再发送给服务器。符号?后面就是参数

https://fanyi.baidu.com/mtpe-individual/multimodal?query=%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96&lang=zh2en

POST方法会将表单的数据存放到请求正文中,再发送给服务器

  • POST传参的数据可以很大,因为存放在正文中;GET方法传参的数据一定很小,因为存放在URL中
  • POST传参比GET传参安全,因为GET传参的数据会直接暴露在URL中。但这两种传参方法都不安全,需要对参数加密,即Https协议

提取GET方法传递的参数代码:

static const std::string argSep="?";//URL中参数的位置标识
//解析URL中携带的参数(GET方法)
if(strcasecmp(_method.c_str(),"GET")==0)//请求方法是GET
{
    auto pos=_url.find(argSep);
    if(pos!=std::string::npos)//URL中携带参数
    {
        _reqContent=_url.substr(pos+argSep.size());//提取URL中的参数,存放到请求正文中
        _url.resize(pos);//URL中去除参数部分
    }
}

三、根据资源类型对应出Content-Type值

根据请求后缀,如.html   .jpg   .png   .gif等对应出Content-Type值

//--------------------------------------------------------
        //建立资源后缀和Http协议中的资源类型之间的映射关系
        //--------------------------------------------------------
        _resourceType.insert({".html", "text/html"});
        _resourceType.insert({".htm", "text/html"});
        _resourceType.insert({".css", "text/css"});
        _resourceType.insert({".txt", "text/plain"});
        _resourceType.insert({".md", "text/markdown"});
        // 脚本类
        _resourceType.insert({".js", "application/javascript"});
        _resourceType.insert({".mjs", "application/javascript"});
        // 图像类
        _resourceType.insert({".jpg", "image/jpeg"});
        _resourceType.insert({".jpeg", "image/jpeg"});
        _resourceType.insert({".png", "image/png"});
        _resourceType.insert({".gif", "image/gif"});
        _resourceType.insert({".webp", "image/webp"});
        _resourceType.insert({".svg", "image/svg+xml"});
        _resourceType.insert({".ico", "image/x-icon"});
        // 字体类
        _resourceType.insert({".woff", "font/woff"});
        _resourceType.insert({".woff2", "font/woff2"});
        _resourceType.insert({".ttf", "font/ttf"});
        // 多媒体类
        _resourceType.insert({".mp3", "audio/mpeg"});
        _resourceType.insert({".wav", "audio/wav"});
        _resourceType.insert({".mp4", "video/mp4"});
        _resourceType.insert({".webm", "video/webm"});
        // 文档类
        _resourceType.insert({".pdf", "application/pdf"});
        _resourceType.insert({".doc", "application/msword"});
        _resourceType.insert({".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"});
        _resourceType.insert({".xls", "application/vnd.ms-excel"});
        _resourceType.insert({".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
        _resourceType.insert({".ppt", "application/vnd.ms-powerpoint"});
        _resourceType.insert({".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"});
        // 压缩包类
        _resourceType.insert({".zip", "application/zip"});
        _resourceType.insert({".tar", "application/x-tar"});
        _resourceType.insert({".gz", "application/gzip"});
        // 数据格式类
        _resourceType.insert({".json", "application/json"});
        _resourceType.insert({".xml", "application/xml"});
        _resourceType.insert({".csv", "text/csv"});
        // 二进制流默认类型
        _resourceType.insert({".bin", "application/octet-stream"});
大类Content-Type值描述
文本类型text/plain纯文本,无格式(如TXT文件)
text/htmlHTML文档,用于网页
text/cssCSS样式表
text/javascriptJavaScript代码(旧标准,推荐使用 application/javascript
text/markdownMarkdown格式文本
图像类型image/jpegJPEG图像
image/pngPNG图像
image/gifGIF图像(支持动画)
image/webpWebP格式图像(现代高效压缩格式)
image/svg+xmlSVG矢量图(基于XML)
应用程序类型application/jsonJSON格式数据,常用于API交互
application/xmlXML数据
application/pdfPDF文档
application/octet-stream二进制流(如文件下载)
application/x-www-form-urlencoded表单提交的默认编码格式
application/zipZIP压缩文件
application/javascriptJavaScript代码(现代标准)
application/wasmWebAssembly模块(用于高性能Web应用)
多媒体类型audio/mpegMP3音频文件
audio/wavWAV音频文件
video/mp4MP4视频文件
video/webmWebM开放格式视频
多部分类型multipart/form-data表单文件上传(支持二进制数据)
multipart/byteranges分块传输响应(用于HTTP范围请求)
字体类型font/woffWeb开放字体格式(WOFF 1.0)
font/woff2WOFF 2.0字体(更高压缩率)
其他类型application/vnd.ms-excelExcel文件(旧版,如 .xls
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet新版Excel文件(.xlsx

四、Http代码

//应用层协议:HTTP协议

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <sstream>
#include <cstring>//提供strcasecmp,忽略大小写比较字符串
#include <memory>//智能指针
#include <fstream>//文件操作

static const std::string baseSep="\r\n";//行与行之间的分隔符
static const std::string lineSep=" ";//请求行中各个属性的分隔符
static const std::string argSep="?";//URL中参数的位置标识
static const std::string homePage="index.html";//主页资源
static const std::string suffixSep=".";//资源后缀符号
static const std::string headerSep=": ";//单个报头属性之间的分隔符
static const std::string webRootDir="wwwroot";//Web根目录(path初始值即为web根目录)
static const std::string httpVersion="HTTP/1.0";//默认的Http协议版本(用于响应)

//Http请求
class HttpRequest
{
private:
    //Http协议请求的基本属性
    std::string _reqLine;//请求行
    std::vector<std::string> _reqHeaders;//请求报头
    std::string _blankLine;//空行
    std::string _reqContent;//请求正文

    //Http协议请求的详细属性
    std::string _method;//请求方法
    std::string _url;//请求资源的路径URL
    std::string _version;//Http版本
    std::unordered_map<std::string,std::string> _reqHeadersKV;//请求报头属性集合(请求报头的各种属性存储在哈希表中)
    std::string _path;//URL只是相对路径,要根据资源所在位置确定绝对路径
    std::string _suffix;//资源后缀,用于确定请求的资源是什么类型,以便填充请求报头中的Content-Type属性
public:
    //构造函数
    HttpRequest()
        :_blankLine(baseSep),
        _path(webRootDir)
    {}
    //析构函数
    ~HttpRequest()
    {}
private:
    //解析请求协议,获取单行数据(目的是将请求行、请求报头、请求正文拆分开)
    std::string GetLine(std::string& reqstr)
    {
        auto pos=reqstr.find(baseSep);//查找\r\n
        if(pos!=std::string::npos)
        {
            std::string line=reqstr.substr(0,pos);
            reqstr.erase(0,pos+baseSep.size());
            if(line.empty()) return baseSep;//如果获取一行的内容是空,说明该行是空行,返回\r\n
            else return line;//否则返回正常获取的一行数据
        }
        else
        {
            return std::string();
        }
    }
    //解析请求行
    void ParseReqLine()
    {
        //将请求行解析为请求方法、URL、http版本
        std::stringstream ss(_reqLine);//按空格为分隔符
        ss>>_method>>_url>>_version;

        //--------------------------------------------------------------
        //更详细地解析URL,以提取参数、初始化path、初始化资源后缀suffix

        //1.提取参数
        //解析URL中携带的参数(GET方法)
        if(strcasecmp(_method.c_str(),"GET")==0)//请求方法是GET
        {
            auto pos=_url.find(argSep);
            if(pos!=std::string::npos)//URL中携带参数
            {
                _reqContent=_url.substr(pos+argSep.size());//提取URL中的参数,存放到请求正文中
                _url.resize(pos);//URL中去除参数部分
            }
        }

        //2.初始化path
        //初始化请求的资源路径path(绝对路径)
        _path+=_url;
        //解析请求的资源路径path,如果请求的是web根目录
        if(_path[_path.size()-1]=='/')
        {
            _path+=homePage;
        }

        //3.初始化资源后缀suffix
        auto pos=_path.rfind(suffixSep);
        if(pos!=std::string::npos)
        {
            _suffix=_path.substr(pos);
        }
        else
        {
            _suffix=".default";
        }
    }
    //解析请求报头
    void ParseReqHeaders()
    {
        //将报头属性存储到哈希表中
        for(auto& reqHeader:_reqHeaders)
        {
            auto pos=reqHeader.find(headerSep);
            if(pos!=std::string::npos)
            {
                std::string k=reqHeader.substr(0,pos);
                std::string v=reqHeader.substr(pos+headerSep.size());
                if(k.empty()||v.empty()) continue;
                _reqHeadersKV[k]=v;
            }
            else
            {
                continue;
            }
        }
    }
public:
    //反序列化:序列化字符串➡基本属性➡详细属性
    void Deserialize(std::string& reqstr)
    {
        //基本的反序列化:拆分reqstr为请求行、请求报头、空行、请求正文

        //请求行
        _reqLine=GetLine(reqstr);
        //请求报头  todo1
        std::string reqHeader;
        while((reqHeader=GetLine(reqstr))!=baseSep)
        {
            _reqHeaders.emplace_back(reqHeader);
        }
        //空行
        _blankLine=baseSep;
        //请求正文  todo2
        _reqContent=reqstr;

        //---------------------------------------------
        //进一步反序列化:解析请求行、请求报头为更详细的属性
        ParseReqLine();
        ParseReqHeaders();
    }
    //获取路径
    std::string GetPath()
    {
        return _path;
    }
    //获取正文内容
    std::string GetReqContent()
    {
        return _reqContent;
    }
    //获取资源后缀
    std::string GetSuffix()
    {
        return _suffix;
    }
    //输出反序列化结果
    void Print()
    {
        std::cout<<"-----------------------------------------"<<std::endl;
        std::cout<<"请求行:"<<_reqLine<<std::endl;
        std::cout<<"请求方法:"<<_method<<std::endl;
        std::cout<<"URL:"<<_url<<std::endl;
        std::cout<<"Http版本:"<<_version<<std::endl;
        for(auto& reqHeader: _reqHeaders)
        {
            std::cout<<"请求报头:"<<reqHeader<<std::endl;
        }
        std::cout<<"空行:"<<_blankLine;
        std::cout<<"请求正文"<<_reqContent<<std::endl;
    }
};

//Http应答
class HttpResponse
{
private:
    //Http协议响应的基本属性
    std::string _statusLine;//状态行
    std::vector<std::string> _resHeaders;//响应报头
    std::string _blankLine;//空行
    std::string _resContent;//响应正文

    //Http协议响应的详细属性
    std::string _version;//http版本
    int _statusCode;//状态码
    std::string _statusDescribe;//状态码描述
    std::unordered_map<std::string,std::string> _resHeadersKV;//响应报头属性集合
public:
    //构造函数
    HttpResponse()
        :_blankLine(baseSep),
        _version(httpVersion)
    {}
    //析构函数
    ~HttpResponse()
    {}
public:
    //序列化
    std::string Serialize()
    {
        //构建状态行
        _statusLine+=_version+lineSep+std::to_string(_statusCode)+lineSep+_statusDescribe+baseSep;
        //构建应答报头
        for(auto& resHeader: _resHeadersKV)
        {
            _resHeaders.emplace_back(resHeader.first+headerSep+resHeader.second+baseSep);
        }
        
        //正式序列化:详细属性➡基本属性➡序列化字符串
        std::string responseStr=_statusLine;//加上状态行
        for(auto& resHeader:_resHeaders)//加上响应报头
        {
            responseStr+=resHeader;
        }
        responseStr+=_blankLine;//加上空行
        responseStr+=_resContent;//加上响应正文

        return responseStr;
    }
    //设置属性

    //设置状态码和状态码描述
    void AddStatusCodeAndDescribe(int statusCode, const std::string& statusDescribe)
    {
        _statusCode=statusCode;
        _statusDescribe=statusDescribe;
    }
    //添加报头属性
    void AddHeader(const std::string& k, const std::string& v)
    {
        _resHeadersKV[k]=v;
    }
    //添加应答正文
    void AddResContent(const std::string& resContent)
    {
        _resContent=resContent;
    }
}; 


//Http处理(将请求处理为应答)
class HttpServer
{
private:
    std::unordered_map<std::string,std::string> _resourceType;//资源类型(根据后缀,判定资源类型)
    std::unordered_map<int,std::string> _codeToDescribe;//状态码-状态码描述
    std::unordered_map<std::string,std::function<HttpResponse(HttpRequest)>> _serviceLists;//服务列表
public:
    //构造函数
    HttpServer()
    {
        //--------------------------------------------------------
        //建立资源后缀和Http协议中的资源类型之间的映射关系
        //--------------------------------------------------------
        _resourceType.insert({".html", "text/html"});
        _resourceType.insert({".htm", "text/html"});
        _resourceType.insert({".css", "text/css"});
        _resourceType.insert({".txt", "text/plain"});
        _resourceType.insert({".md", "text/markdown"});
        // 脚本类
        _resourceType.insert({".js", "application/javascript"});
        _resourceType.insert({".mjs", "application/javascript"});
        // 图像类
        _resourceType.insert({".jpg", "image/jpeg"});
        _resourceType.insert({".jpeg", "image/jpeg"});
        _resourceType.insert({".png", "image/png"});
        _resourceType.insert({".gif", "image/gif"});
        _resourceType.insert({".webp", "image/webp"});
        _resourceType.insert({".svg", "image/svg+xml"});
        _resourceType.insert({".ico", "image/x-icon"});
        // 字体类
        _resourceType.insert({".woff", "font/woff"});
        _resourceType.insert({".woff2", "font/woff2"});
        _resourceType.insert({".ttf", "font/ttf"});
        // 多媒体类
        _resourceType.insert({".mp3", "audio/mpeg"});
        _resourceType.insert({".wav", "audio/wav"});
        _resourceType.insert({".mp4", "video/mp4"});
        _resourceType.insert({".webm", "video/webm"});
        // 文档类
        _resourceType.insert({".pdf", "application/pdf"});
        _resourceType.insert({".doc", "application/msword"});
        _resourceType.insert({".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"});
        _resourceType.insert({".xls", "application/vnd.ms-excel"});
        _resourceType.insert({".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
        _resourceType.insert({".ppt", "application/vnd.ms-powerpoint"});
        _resourceType.insert({".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"});
        // 压缩包类
        _resourceType.insert({".zip", "application/zip"});
        _resourceType.insert({".tar", "application/x-tar"});
        _resourceType.insert({".gz", "application/gzip"});
        // 数据格式类
        _resourceType.insert({".json", "application/json"});
        _resourceType.insert({".xml", "application/xml"});
        _resourceType.insert({".csv", "text/csv"});
        // 二进制流默认类型
        _resourceType.insert({".bin", "application/octet-stream"});

        //--------------------------------------------------------
        // 建立状态码和状态码描述之间的映射关系
        //--------------------------------------------------------
        // 1xx 信息响应
        _codeToDescribe.insert(std::make_pair(100, "Continue"));
        _codeToDescribe.insert(std::make_pair(101, "Switching Protocols"));
        _codeToDescribe.insert(std::make_pair(102, "Processing"));
        // 2xx 成功
        _codeToDescribe.insert(std::make_pair(200, "OK"));
        _codeToDescribe.insert(std::make_pair(201, "Created"));
        _codeToDescribe.insert(std::make_pair(202, "Accepted"));
        _codeToDescribe.insert(std::make_pair(204, "No Content"));
        _codeToDescribe.insert(std::make_pair(206, "Partial Content"));
        // 3xx 重定向
        _codeToDescribe.insert(std::make_pair(300, "Multiple Choices"));
        _codeToDescribe.insert(std::make_pair(301, "Moved Permanently"));
        _codeToDescribe.insert(std::make_pair(302, "Found"));
        _codeToDescribe.insert(std::make_pair(304, "Not Modified"));
        _codeToDescribe.insert(std::make_pair(307, "Temporary Redirect"));
        _codeToDescribe.insert(std::make_pair(308, "Permanent Redirect"));
        // 4xx 客户端错误
        _codeToDescribe.insert(std::make_pair(400, "Bad Request"));
        _codeToDescribe.insert(std::make_pair(401, "Unauthorized"));
        _codeToDescribe.insert(std::make_pair(403, "Forbidden"));
        _codeToDescribe.insert(std::make_pair(404, "Not Found"));
        _codeToDescribe.insert(std::make_pair(405, "Method Not Allowed"));
        _codeToDescribe.insert(std::make_pair(408, "Request Timeout"));
        _codeToDescribe.insert(std::make_pair(413, "Payload Too Large"));
        _codeToDescribe.insert(std::make_pair(415, "Unsupported Media Type"));
        _codeToDescribe.insert(std::make_pair(429, "Too Many Requests"));
        // 5xx 服务端错误
        _codeToDescribe.insert(std::make_pair(500, "Internal Server Error"));
        _codeToDescribe.insert(std::make_pair(501, "Not Implemented"));
        _codeToDescribe.insert(std::make_pair(502, "Bad Gateway"));
        _codeToDescribe.insert(std::make_pair(503, "Service Unavailable"));
        _codeToDescribe.insert(std::make_pair(504, "Gateway Timeout"));
        _codeToDescribe.insert(std::make_pair(505, "HTTP Version Not Supported"));
    }
private:
    //获取文件资源
    std::string GetResource(const std::string& path)
    {
        std::ifstream file(path, std::ios::binary);//二进制方式打开path路径下的文件
        if(!file.is_open())//文件打开失败
        {
            return std::string();
        }
        file.seekg(0,file.end);//移动输入流指针到文件末尾
        int fileSize=file.tellg();//获取当前输入流指针位置,即获取文件大小
        file.seekg(0,file.beg);//回复输入流指针到文件开头

        std::string resource;
        resource.resize(fileSize);
        file.read((char *)resource.c_str(),fileSize);//读取文件资源内容存放到resource中
        file.close();//关闭文件
        return resource;
    }
public:
    //处理服务端接收到的Http请求,最后返回Http应答序列化后的字符串
    std::string Handle(std::string reqstr)
    {
        //参数说明:reqstr是客户端序列化过的Http请求

        HttpRequest req;
        req.Deserialize(reqstr);//反序列化


        //处理Http请求,转为Http应答
        HttpResponse res;

        if(req.GetPath()=="wwwroot/redir")//处理重定向,重定向到qq官网
        {
            std::string redirPath="https://www.qq.com";
            res.AddStatusCodeAndDescribe(301,_codeToDescribe[301]);
            res.AddHeader("Location",redirPath);
        }
        else if(!req.GetReqContent().empty())//处理参数,如果请求正文不为空,说明传递了参数,请求的不是资源,而是某个服务,要进行服务处理
        {
            if(_serviceLists.find(req.GetPath())!=_serviceLists.end())
            {
                res=_serviceLists[req.GetPath()](req);//该服务是一个处理函数,参数是req,返回值是res
            }
        }
        else//既没有重定向,也没有请求服务,那么直接进行序列化并返回请求的资源
        {
            std::string resource=GetResource(req.GetPath());//获取请求资源的内容
            if(resource.empty())//说明没有该资源,返回404.html资源
            {
                resource=GetResource("wwwroot/404.html");
                res.AddStatusCodeAndDescribe(404,_codeToDescribe[404]);
                res.AddHeader("Content-Length",std::to_string(resource.size()));
                res.AddHeader("Content-Type",_resourceType[".html"]);
                res.AddResContent(resource);
            }
            else
            {
                res.AddStatusCodeAndDescribe(200,_codeToDescribe[200]);
                res.AddHeader("Content-Length", std::to_string(resource.size()));
                res.AddHeader("Content-Type", _resourceType[req.GetSuffix()]);
                //res.AddHeader("Set-Cookie", "username=zhangsan");  //Cookie
                res.AddResContent(resource);
            }
        }

        return res.Serialize();//返回Http应答序列化后的字符串
    }

    //添加处理服务(当Http请求中携带参数时,说明其要请求的是某个服务,而不是资源)
    void InsertService(const std::string& serviceName, std::function<HttpResponse(HttpRequest)> service)
    {
        _serviceLists.insert(std::make_pair(serviceName+webRootDir,service));
    }
};

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

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

相关文章

网络探索之旅:网络原理(第二弹)

上篇文章&#xff0c;小编分享了应用层和传输层深入的一点的知识&#xff0c;那么接下来&#xff0c;这篇文章&#xff0c;继续分享网络层和数据链路层。 网络层 了解这个网络层&#xff0c;那么其实就是重点来了解下IP这个协议 对于这个协议呢&#xff0c;其实也是和前面的…

深入剖析 JVM:从组成原理到调优实践

深入剖析 JVM&#xff1a;从组成原理到调优实践 深入剖析 JVM&#xff1a;从组成原理到调优实践一、JVM 组成架构&#xff1a;运行 Java 程序的 “幕后引擎”1.1 内存结构&#xff1a;数据存储的 “分区管理”1.2 执行引擎&#xff1a;字节码的 “翻译官”1.3 本地方法接口&…

阿里云下一代可观测时序引擎-MetricStore 2.0

作者&#xff1a;徐昊&#xff08;博澍&#xff09; 背景 作为可观测场景使用频度最高的数据类型&#xff0c;Metrics 时序数据在可观测领域一直占有着重要地位&#xff0c;无论是从全局视角来观测系统整体状态&#xff0c;还是从大范围数据中定位某一个异常的位置&#xff0…

从入门到精通【 MySQL】 数据库约束与设计

文章目录 &#x1f4d5;1. 数据库约束✏️1.1 NOT NULL 非空约束✏️1.2 DEFAULT 默认值约束✏️1.3 UNIQUE 唯一约束✏️1.4 PRIMARY KEY 主键约束✏️1.5 FOREIGN KEY 外键约束✏️1.6 CHECK 约束 &#x1f4d5;2. 数据库设计✏️2.1 第一范式✏️2.2 第二范式✏️2.3 第三范…

Dubbo 通信流程 - 服务的调用

Dubbo 客户端的使用 在 Dubbo 应用中&#xff0c;往类成员注解 DubboReference&#xff0c;服务启动后便可以调用到远端&#xff1a; Component public class InvokeDemoFacade {AutowiredDubboReferenceprivate DemoFacade demoFacade;public String hello(String name){// …

【数据结构】哈夫曼树

哈夫曼树 在学习哈夫曼树之前&#xff0c;先了解以下几个概念&#xff1a; 一&#xff1a;**路径长度&#xff1a;**在一棵树中&#xff0c;从一个节点到另一个节点所经过的“边”的数量&#xff0c;被我们称为两个节点之间的路径长度。 二&#xff1a;**树的路径长度&#xf…

HCIP(TCP)(2)

1. TCP三次握手 SYN (同步序列编号) 报文: 客户端发送 SYN 报文&#xff0c;开始建立连接&#xff0c;并初始化序列号。 SYN-ACK (同步序列编号-确认) 报文: 服务器收到 SYN 报文后&#xff0c;回复 SYN-ACK 报文&#xff0c;确认连接请求&#xff0c;并初始化自己的序列号和确…

基于Web的交互式智能成绩管理系统设计

目录 摘要 绪论 一、应用背景 二、行业发展现状 三、程序开发的重要意义 四、结语 1 代码 2 数据初始化模块 3 界面布局模块 4 核心功能模块 5 可视化子系统 6 扩展功能模块 7 架构设计亮点 功能总结 一、核心数据管理 二、智能分析体系 三、可视化系统 四、扩…

k8s日志管理

k8s日志管理 k8s查看日志查看集群中不是完全运行状态的pod查看deployment日志查看service日志进入pod的容器内查看日志 管理k8s组件日志kubectl logs查看日志原理 管理k8s应用日志收集k8s日志思路收集标准输出收集容器中日志文件 k8s查看节点状态失败k8s部署prometheus监控 k8s…

element-plus中,Loading 加载组件的使用

一.基本使用 给一个组件&#xff0c;如&#xff1a;table表格&#xff0c;加上v-loading"true"即可。 举例&#xff1a;复制如下代码。 <template><el-table v-loading"loading" :data"tableData" style"width: 100%"><…

Mybatis_Plus中的常用注解

目录 1、TableName TableId TableId的type属性 TableField 1、TableName 经过以上的测试&#xff0c;在使用MyBatis-Plus实现基本的CRUD时&#xff0c;我们并没有指定要操作的表&#xff0c;只是在 Mapper接口继承BaseMapper时&#xff0c;设置了泛型User&#xff0c;而操…

高并发金融系统,“可观测-可追溯-可回滚“的闭环审计体系

一句话总结 在高并发金融系统中&#xff0c;审计方案设计需平衡"观测粒度"与"系统损耗"&#xff0c;通过双AOP实现非侵入式采集&#xff0c;三表机制保障操作原子性&#xff0c;最终形成"可观测-可追溯-可回滚"的闭环体系。 业务痛点与需求 在…

企业内训|DeepSeek技术革命、算力范式重构与场景落地洞察-某头部券商

3月19日北京&#xff0c;TsingtaoAI公司负责人汶生受邀为某证券公司管理层和投资者举办专题培训&#xff0c;围绕《DeepSeek技术革命、算力范式重构与场景落地洞察》主题&#xff0c;系统阐述了当前AI技术演进的核心趋势、算力需求的结构性变革&#xff0c;以及行业应用落地的关…

VS Code C/C++项目设置launch.json中的environment参数解决支持库路径问题

问题描述 Windows 11 VS Code C/C 开发环境搭建分别写了c和cpp两个示例代码&#xff0c;在运行过程中c代码没有发现问题&#xff08;可能简单&#xff0c;没有用到太多支持&#xff09;&#xff0c;但使用了stl的cpp代码并没有运行出来&#xff0c;如下图&#xff1a; 出问题…

怎样解决 Windows 11 上的 DirectX 错误,最新DX 问题解决方法

在使用 Windows 11 操作系统的过程中&#xff0c;大家可能会遇到 DirectX 错误的情况&#xff0c;这可能会给游戏体验、多媒体应用甚至是系统的整体性能带来负面影响。不过别担心&#xff0c;本文将为大家详细介绍如何解决 Windows 11 上的 DirectX 错误&#xff0c;让您的系统…

PH热榜 | 2025-03-30

1. Deepcord 标语&#xff1a;Discord 数据分析&#xff1a;获取指标洞察与受众研究 介绍&#xff1a;Deepcord&#xff1a;为社区建设者提供的Discord分析工具。跟踪超过50万个服务器的指标&#xff0c;发现热门社区&#xff0c;监控竞争对手&#xff0c;找到你的目标受众。…

Open webui的使用

问题 之前本地量化模型管理器ollama的文章&#xff0c;我们知道可以通过ollama来管理本地量化模型&#xff0c;也能够在命令行中与相关模型进行对话。现在我们想要在有个web页面通过浏览器来与本地模型对话。这里我们就使用Open webui作为界面来与本地模型对话。 安装启动 这…

STM32单片机的桌面宠物机器人(基于HAL库)

效果 基于STM32单片机的桌面宠物机器人 概要 语音模块&#xff1a;ASR PRO&#xff0c;通过天问block软件烧录语音指令 主控芯片&#xff1a;STM32F103C8T6 使用HAL库 屏幕&#xff1a;0.96寸OLED屏&#xff0c;用来显示表情 4个舵机&#xff0c;用来当作四只腿 底部一个面…