最新获取网站访客qq接口/爱站网关键词长尾挖掘

最新获取网站访客qq接口,爱站网关键词长尾挖掘,网站系统繁忙是什么意思,网站开发公司外包文章目录 HTTP 请求报文HttpRequest 类实现 Init() 函数实现 ParseRequestLine() 函数实现 ParseHeader() 函数实现 ParsePath() 函数实现 ParseBody() 函数实现 ParsePost() 函数实现 ParseFromUrlEncoded() 函数实现 UserVerify() 函数实现 Parse() 函数HttpRequest 代码Http…

文章目录

  • HTTP 请求报文
  • HttpRequest 类
  • 实现 Init() 函数
  • 实现 ParseRequestLine() 函数
  • 实现 ParseHeader() 函数
  • 实现 ParsePath() 函数
  • 实现 ParseBody() 函数
  • 实现 ParsePost() 函数
  • 实现 ParseFromUrlEncoded() 函数
  • 实现 UserVerify() 函数
  • 实现 Parse() 函数
  • HttpRequest 代码
  • HttpRequest 测试

从零开始实现 C++ TinyWebServer 项目总览
项目源码

HTTP 请求报文

 2025-02-27 200519.png

 2025-02-27 200654.png

一个典型的 HTTP 请求包含请求行、请求头和请求体(可选)。

  • 请求行:包含请求方法(如 GETPOST 等)、请求路径(如 /index.html)和 HTTP 版本(如 HTTP/1.1)。
  • 请求头:包含多个键值对,用于传递额外的信息,如 HostUser-Agent 等。
  • 请求体:通常在 POST 请求中使用,用于传递数据。

HttpRequest 类

在 Web 服务器中,HttpRequest类起着至关重要的作用,主要负责处理客户端发送的 HTTP 请求。具体来说,它承担了以下几个关键任务:

  1. 请求解析:接收客户端发送的 HTTP 请求报文,并对其进行解析,将请求报文中的各个部分(如请求行、请求头、请求体等)提取出来,以便后续处理。
  2. 状态管理:在解析过程中,通过状态机来管理解析的状态,确保解析过程的正确性和顺序性。
  3. 请求处理:根据解析结果,进行相应的处理,例如处理 GET 请求、POST 请求等,并根据请求的内容和服务器的配置,决定如何响应客户端。
class HttpRequest {
public:enum PARSE_STATE {REQUEST_LINE,HEADERS,BODY,FINISH};HttpRequest() { Init(); }~HttpRequest() = default;void Init();bool Parse(Buffer& buff);std::string Method() const;std::string Path() const;std::string& Path();std::string Version() const;std::string GetPost(const std::string& key) const;std::string GetPost(const char* key) const;bool IsKeepAlive() const;private:static int ConverHex(char ch);	// 16进制转10进制static bool UserVerify(const std::string& name, const std::string& pwd, bool is_login);	// 验证用户bool ParseRequestLine(const std::string& line);	// 解析请求行void ParseHeader(const std::string& line);		// 解析请求头void ParseBody(const std::string& line);		// 解析请求体void ParsePath();	// 解析请求路径void ParsePost();	// 解析Post事件void ParseFromUrlEncoded();	// 解析urlstatic const std::unordered_set<std::string> DEFAULT_HTML;static const std::unordered_map<std::string, int> DEFAULT_HTML_TAG;PARSE_STATE state_;std::string method_;std::string path_;std::string version_;std::string body_;std::unordered_map<std::string, std::string> header_; // HTTP 请求的头部信息std::unordered_map<std::string, std::string> post_;   // POST 请求的数据
};

实现 Init() 函数

void HttpRequest::Init() {state_ = REQUEST_LINE;method_ = path_ = version_ = body_ = "";header_.clear();post_.clear();
}

实现 ParseRequestLine() 函数

  • 使用正则表达式^([^ ]*) ([^ ]*) HTTP/([^ ]*)$以及std::regex_match来匹配请求行。
  • 若匹配成功,将匹配结果分别存储到method_path_version_中,并将解析状态设置为HEADERS,表示接下来要解析请求头,返回true
bool HttpRequest::ParseRequestLine(const std::string& line) {// GET /index.html HTTP/1.1std::regex patten("^([^ ]*) ([^ ]*) HTTP/([^ ]*)$");std::smatch match;// 匹配指定字符串整体是否符合if (std::regex_match(line, match, patten)) { method_ = match[1];path_ = match[2];version_ = match[3];state_ = HEADERS;return true;} LOG_ERROR("RequestLine Error"); return false;
}

实现 ParseHeader() 函数

  • 如果路径为/,则将其修改为/index.html
  • 否则,检查路径是否在DEFAULT_HTML中,如果存在则在路径后面添加.html后缀。
void HttpRequest::ParseHeader(const std::string& line) {std::regex patten("^([^:]*): ?(.*)$");std::smatch match;if (std::regex_match(line, match, patten)) {header_[match[1]] = match[2];} else {state_ = BODY;}
}

实现 ParsePath() 函数

  • 如果路径为/,则将其修改为/index.html
  • 否则,检查路径是否在DEFAULT_HTML中,如果存在则在路径后面添加.html后缀
void HttpRequest::ParsePath() {if (path_ == "/") {path_ = "/index.html";} else {if (DEFAULT_HTML.find(path_) != DEFAULT_HTML.end())path_ += ".html";}
}

实现 ParseBody() 函数

  • 将请求体内容存储到body_中。
  • 调用ParsePost函数处理 POST 请求数据。
  • 将解析状态设置为FINISH,表示解析完成。
void HttpRequest::ParseBody(const std::string& line) {body_ = line;ParsePost();    state_ = FINISH;LOG_DEBUG("Body: %s, len: %d", line.c_str(), line.size());
}

实现 ParsePost() 函数

  • 检查请求方法是否为POST,并且请求头中的Content-Type是否为application/x-www-form-urlencoded
  • 如果满足条件,调用ParseFromUrlencoded函数解析 URL 编码的请求体。
  • 检查路径是否为登录或注册相关路径,如果是则调用UserVerify函数,进行用户验证,根据验证结果设置相应的跳转路径。
void HttpRequest::ParsePost() {if (method_ == "POST" && header_["Content-Type"] == "application/x-www-form-urlencoded") {ParseFromUrlEncoded();if (DEFAULT_HTML_TAG.count(path_)) { // 登录/注册int tag = DEFAULT_HTML_TAG.find(path_)->second;LOG_DEBUG("Tag: %d", tag);if (tag == 0 || tag == 1) {bool is_login = (tag == 1);if (UserVerify(post_["username"], post_["password"], is_login))path_ = "/welcome.html";elsepath_ = "/error.html";}}}
}

实现 ParseFromUrlEncoded() 函数

  • 首先检查请求体是否为空,如果为空则直接返回。
  • 遍历请求体字符串,根据不同的字符进行不同的处理:
    • 遇到=,将之前的字符作为键存储到key中,并更新起始位置j
    • 遇到&,将之前的字符作为值存储到value中,并将键值对存储到post_容器中,同时更新起始位置j
    • 遇到+,将其替换为空格。
    • 遇到%,将其后的两个十六进制字符转换为十进制整数,并更新请求体内容。
  • 最后处理剩余的键值对。
void HttpRequest::ParseFromUrlEncoded() {if (body_.size() == 0)return;std::string key, value;int num = 0;int n = body_.size();int i = 0, j = 0;while (i < n) {char ch = body_[i];// username=john%20doe&password=123456switch (ch) {case '=': // 获取键值对key = body_.substr(j, i - j); j = i + 1;break;case '&': // 获取键值对value = body_.substr(j, i - j);j = i + 1;post_[key] = value;LOG_DEBUG("%s = %s", key.c_str(), value.c_str());break;case '+': // 替换为空格body_[i] = ' ';break;case '%':num = ConverHex(body_[i + 1]) * 16 + ConverHex(body_[i + 2]);body_[i + 2] = num % 10 + '0';body_[i + 1] = num / 10 + '0';i += 2;break;default:break;}i++;}assert(j <= i);if (post_.count(key) == 0 && j < i) {value = body_.substr(j, i - j);post_[key] = value;}
}

实现 UserVerify() 函数

  • 首先检查用户名和密码是否为空,如果为空则返回false
  • 使用SqlConnRAII管理数据库连接,构造查询语句,查询数据库中是否存在该用户名。
  • 如果是登录行为,比较输入的密码和数据库中的密码是否一致,一致则验证成功。
  • 如果是注册行为,检查用户名是否已被使用,若未被使用则将用户信息插入数据库。
// 验证用户的用户名和密码
bool HttpRequest::UserVerify(const std::string& name, const std::string& pwd, bool is_login) {if (name == "" || pwd == "")return false;LOG_INFO("Verify name: %s pwd: %s", name.c_str(), pwd.c_str());MYSQL* sql;SqlConnectRAII(&sql, SqlConnectPool::GetInstance());assert(sql);bool flag = false;char order[256] = {0};MYSQL_RES* res = nullptr;      // 查询结果集if (!is_login) // 注册flag = true;snprintf(order, 256, "SELECT username, password FROM User WHERE username='%s' LIMIT 1", name.c_str());LOG_DEBUG("%s", order);// 查询用户信息if (mysql_query(sql, order)) {if (res)mysql_free_result(res); // 查询失败,释放结果集return false;}res = mysql_store_result(sql);   // 存储查询结果到res中// 处理查询结果while (MYSQL_ROW row = mysql_fetch_row(res)) {LOG_DEBUG("MYSQL ROW: %s %s", row[0], row[1]);std::string password = row[1];if (is_login) {if (pwd == password) {flag = true;} else {flag = false;LOG_INFO("pwd error!");}} else {flag = false;LOG_INFO("user used!");}}mysql_free_result(res);// 注册(用户名未被使用)if (!is_login && flag) {LOG_DEBUG("register");bzero(order, 256);snprintf(order, 256, "INSERT INTO User(username, password) VALUES('%s', '%s')", name.c_str(), pwd.c_str());LOG_DEBUG("%s", order);if (mysql_query(sql, order)) {LOG_ERROR("MySQL insert fail: Error: %s", mysql_error(sql));flag = false;} else {LOG_DEBUG("UserVerify success!");flag = true;}}return flag;
}

实现 Parse() 函数

  • 首先检查Buffer中是否有可读数据,如果没有则返回false

  • 循环读取Buffer中的数据,直到没有可读数据或者解析状态为FINISH

  • 利用search函数查找\r\n来确定每行数据的结束位置,将每行数据提取出来存为line

  • 根据当前解析状态state_的不同,调用不同的解析函数进行处理:

    • 若为REQUEST_LINE状态,调用ParseRequestLine_解析请求行,若解析失败则返回false,成功则继续解析路径。
    • 若为HEADERS状态,调用ParseHeader_解析请求头,若Buffer中剩余可读字节小于等于 2,则认为是 GET 请求,将状态设置为FINISH
    • 若为BODY状态,调用ParseBody_解析请求体。
  • 如果lineend到达Buffer的写指针位置,说明数据读完,调用buff.RetrieveAll()清空Buffer,并跳出循环;否则跳过\r\n继续解析。

  • 最后记录解析出的请求方法、路径和版本信息,并返回true表示解析成功。

bool HttpRequest::Parse(Buffer& buff) {const char* END = "\r\n";if (buff.ReadableBytes() == 0)return false;while (buff.ReadableBytes() && state_ != FINISH) {// 找到buff中,首次出现"\r\n"的位置const char* line_end = std::search(buff.ReadBegin(), buff.WriteBeginConst(), END, END + 2);string line(buff.ReadBegin(), line_end);switch (state_) {case REQUEST_LINE:if (ParseRequestLine(line) == false)return false;ParsePath();break;case HEADERS:ParseHeader(line);if (buff.ReadableBytes() <= 2) // get请求,提前结束state_ = FINISH;break;case BODY:ParseBody(line);break;default:break;}if (line_end == buff.WriteBegin()) { // 读完了buff.RetrieveAll();break;}buff.RetrieveUntil(line_end + 2); // 跳过回车换行}LOG_DEBUG("[%s] [%s] [%s]", method_ .c_str(), path_.c_str(), version_.c_str());return true;
}

HttpRequest 代码

http_request.h

#ifndef HTTP_REQUEST_H
#define HTTP_REQUEST_H#include <cstring>
#include <string>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <regex> // 正则表达式
#include <mysql/mysql.h>#include "../buffer/buffer.h"
#include "../log/log.h"
#include "../pool/sql_connect_pool.h"class HttpRequest {
public:enum PARSE_STATE {REQUEST_LINE,HEADERS,BODY,FINISH};HttpRequest() { Init(); }~HttpRequest() = default;void Init();bool Parse(Buffer& buff);std::string Method() const;std::string Path() const;std::string& Path();std::string Version() const;std::string GetPost(const std::string& key) const;std::string GetPost(const char* key) const;bool IsKeepAlive() const;private:static int ConverHex(char ch);static bool UserVerify(const std::string& name, const std::string& pwd, bool is_login);bool ParseRequestLine(const std::string& line);void ParseHeader(const std::string& line);void ParseBody(const std::string& line);void ParsePath();void ParsePost();void ParseFromUrlEncoded();static const std::unordered_set<std::string> DEFAULT_HTML;static const std::unordered_map<std::string, int> DEFAULT_HTML_TAG;PARSE_STATE state_;std::string method_;std::string path_;std::string version_;std::string body_;std::unordered_map<std::string, std::string> header_; // HTTP 请求的头部信息std::unordered_map<std::string, std::string> post_;   // POST 请求的数据
};#endif // HTTP_REQUEST_H

http_request.cc

#include "http_request.h"const std::unordered_set<std::string> HttpRequest::DEFAULT_HTML {"/index", "/register", "/login", "/welcome", "/video", "/picture"
};// 登录/注册
const std::unordered_map<std::string, int> HttpRequest::DEFAULT_HTML_TAG {{"/login.html", 1}, {"/register.html", 0}
};void HttpRequest::Init() {state_ = REQUEST_LINE;method_ = path_ = version_ = body_ = "";header_.clear();post_.clear();
}bool HttpRequest::ParseRequestLine(const std::string& line) {// GET /index.html HTTP/1.1std::regex patten("^([^ ]*) ([^ ]*) HTTP/([^ ]*)$");std::smatch match;if (std::regex_match(line, match, patten)) {method_ = match[1];path_ = match[2];version_ = match[3];state_ = HEADERS;return true;} LOG_ERROR("RequestLine Error"); return false;
}void HttpRequest::ParseHeader(const std::string& line) {std::regex patten("^([^:]*): ?(.*)$");std::smatch match;if (std::regex_match(line, match, patten)) {header_[match[1]] = match[2];} else {state_ = BODY;}
}void HttpRequest::ParseBody(const std::string& line) {body_ = line;ParsePost();    state_ = FINISH;LOG_DEBUG("Body: %s, len: %d", line.c_str(), line.size());
}void HttpRequest::ParsePost() {if (method_ == "POST" && header_["Content-Type"] == "application/x-www-form-urlencoded") {ParseFromUrlEncoded();if (DEFAULT_HTML_TAG.count(path_)) { // 登录/注册int tag = DEFAULT_HTML_TAG.find(path_)->second;LOG_DEBUG("Tag: %d", tag);if (tag == 0 || tag == 1) {bool is_login = (tag == 1);if (UserVerify(post_["username"], post_["password"], is_login))path_ = "/welcome.html";elsepath_ = "/error.html";}}}
}// 16进制转10进制
int HttpRequest::ConverHex(char ch) {if (ch >= 'A' && ch <= 'F')return ch - 'A' + 10;if (ch >= 'a' && ch <= 'f')return ch - 'a' + 10;return ch;
}void HttpRequest::ParseFromUrlEncoded() {if (body_.size() == 0)return;std::string key, value;int num = 0;int n = body_.size();int i = 0, j = 0;while (i < n) {char ch = body_[i];// username=john%20doe&password=123456switch (ch) {case '=': // 获取键值对key = body_.substr(j, i - j); j = i + 1;break;case '&': // 获取键值对value = body_.substr(j, i - j);j = i + 1;post_[key] = value;LOG_DEBUG("%s = %s", key.c_str(), value.c_str());break;case '+': // 替换为空格body_[i] = ' ';break;case '%':num = ConverHex(body_[i + 1]) * 16 + ConverHex(body_[i + 2]);body_[i + 2] = num % 10 + '0';body_[i + 1] = num / 10 + '0';i += 2;break;default:break;}i++;}assert(j <= i);if (post_.count(key) == 0 && j < i) {value = body_.substr(j, i - j);post_[key] = value;}
}void HttpRequest::ParsePath() {if (path_ == "/") {path_ = "/index.html";} else {if (DEFAULT_HTML.find(path_) != DEFAULT_HTML.end())path_ += ".html";}
}// 验证用户的用户名和密码
bool HttpRequest::UserVerify(const std::string& name, const std::string& pwd, bool is_login) {if (name == "" || pwd == "")return false;LOG_INFO("Verify name: %s pwd: %s", name.c_str(), pwd.c_str());MYSQL* sql;SqlConnectRAII(&sql, SqlConnectPool::GetInstance());assert(sql);bool flag = false;char order[256] = {0};MYSQL_RES* res = nullptr;      // 查询结果集if (!is_login) // 注册flag = true;snprintf(order, 256, "SELECT username, password FROM User WHERE username='%s' LIMIT 1", name.c_str());LOG_DEBUG("%s", order);// 查询用户信息if (mysql_query(sql, order)) {if (res)mysql_free_result(res); // 查询失败,释放结果集return false;}res = mysql_store_result(sql);   // 存储查询结果到res中// 处理查询结果while (MYSQL_ROW row = mysql_fetch_row(res)) {LOG_DEBUG("MYSQL ROW: %s %s", row[0], row[1]);std::string password = row[1];if (is_login) {if (pwd == password) {flag = true;} else {flag = false;LOG_INFO("pwd error!");}} else {flag = false;LOG_INFO("user used!");}}mysql_free_result(res);// 注册(用户名未被使用)if (!is_login && flag) {LOG_DEBUG("register");bzero(order, 256);snprintf(order, 256, "INSERT INTO User(username, password) VALUES('%s', '%s')", name.c_str(), pwd.c_str());LOG_DEBUG("%s", order);if (mysql_query(sql, order)) {LOG_ERROR("MySQL insert fail: Error: %s", mysql_error(sql));flag = false;} else {LOG_DEBUG("UserVerify success!");flag = true;}}return flag;
}bool HttpRequest::Parse(Buffer& buff) {const char* END = "\r\n";if (buff.ReadableBytes() == 0)return false;while (buff.ReadableBytes() && state_ != FINISH) {// 找到buff中,首次出现"\r\n"的位置const char* line_end = std::search(buff.ReadBegin(), buff.WriteBeginConst(), END, END + 2);string line(buff.ReadBegin(), line_end);switch (state_) {case REQUEST_LINE:if (ParseRequestLine(line) == false)return false;ParsePath();break;case HEADERS:ParseHeader(line);if (buff.ReadableBytes() <= 2) // get请求,提前结束state_ = FINISH;break;case BODY:ParseBody(line);break;default:break;}if (line_end == buff.WriteBegin()) { // 读完了buff.RetrieveAll();break;}buff.RetrieveUntil(line_end + 2); // 跳过回车换行}LOG_DEBUG("[%s] [%s] [%s]", method_ .c_str(), path_.c_str(), version_.c_str());return true;
}std::string HttpRequest::Method() const {return method_;
}std::string HttpRequest::Path() const {return path_;
}std::string& HttpRequest::Path() {return path_;
}std::string HttpRequest::Version() const {return version_;
}std::string HttpRequest::GetPost(const std::string& key) const {if (post_.count(key) == 1)// return post_[key]; post_有const属性,所以不能用[]return post_.find(key)->second;return "";
}std::string HttpRequest::GetPost(const char* key) const {assert(key != nullptr);if (post_.count(key) == 1)return post_.find(key)->second;return "";
}bool HttpRequest::IsKeepAlive() const {if (header_.count("Connect") == 1) return header_.find("Connect")->second == "keep-alive" && version_ == "1.1";return false;
}

HttpRequest 测试

测试HttpRequest的,解析,注册,登录功能

#include "../code/http/http_request.h"
#include <iostream>void TestHttpRequest() {// 初始化日志系统Log* logger = Log::GetInstance();logger->Init(0, "./logs/", ".log", 1024);// 初始化测试HttpRequest request;// 初始化数据库连接池SqlConnectPool* conn_pool = SqlConnectPool::GetInstance();conn_pool->Init("localhost", 3306, "Tian", "123456", "web_server", 10);// 解析请求测试std::string http_request = "GET /index.html HTTP/1.1\r\n""Host: example.com\r\n""Connection: keep-alive\r\n""\r\n";Buffer buff;buff.Append(http_request);bool parseResult = request.Parse(buff);assert(parseResult);// 访问器方法测试assert(request.Method() == "GET");assert(request.Path() == "/index.html");assert(request.Version() == "1.1");// 模拟注册 POST 请求std::string register_request = "POST /register.html HTTP/1.1\r\n""Host: example.com\r\n""Content-Type: application/x-www-form-urlencoded\r\n""Content-Length: 23\r\n""\r\n""username=test&password=123456";request.Init();buff.Append(register_request);parseResult = request.Parse(buff);assert(parseResult);assert(request.Method() == "POST");assert(request.Path() == "/welcome.html");assert(request.Version() == "1.1");assert(request.GetPost("username") == "test");assert(request.GetPost("password") == "123456");// Post 数据获取测试// 模拟登录 POST 请求std::string login_request = "POST /login HTTP/1.1\r\n""Content-Type: application/x-www-form-urlencoded\r\n""Content-Length: 19\r\n""\r\n""username=test&password=123456""\r\n";buff.Append(login_request);request.Init();parseResult = request.Parse(buff);assert(parseResult);assert(request.Method() == "POST");assert(request.Path() == "/welcome.html");assert(request.Version() == "1.1");assert(request.GetPost("username") == "test");assert(request.GetPost("password") == "123456");std::cout << "All tests passed!" << std::endl;
}int main() {TestHttpRequest();return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(tests)# 设置 C++ 标准和编译器选项
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")# 定义公共源文件和特定文件
set(COMMON_SOURCES ../code/buffer/buffer.cc ../code/log/log.cc)
set(HTTP_SOURCE ../code/http/http_request.cc)
set(POOL_SOURCE ../code/pool/sql_connect_pool.cc)# 查找 MySQL 库
find_package(PkgConfig REQUIRED)
pkg_check_modules(MYSQL REQUIRED mysqlclient)
# 包含 MySQL 头文件目录
include_directories(${MYSQL_INCLUDE_DIR})# 添加可执行文件
add_executable(http_request_test http_request_test.cc ${COMMON_SOURCES} ${HTTP_SOURCE} ${POOL_SOURCE})
# 链接库
target_link_libraries(http_request_test ${MYSQL_LIBRARIES})

return 0;
}


**CMakeLists.txt**```cmake
cmake_minimum_required(VERSION 3.10)
project(tests)# 设置 C++ 标准和编译器选项
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")# 定义公共源文件和特定文件
set(COMMON_SOURCES ../code/buffer/buffer.cc ../code/log/log.cc)
set(HTTP_SOURCE ../code/http/http_request.cc)
set(POOL_SOURCE ../code/pool/sql_connect_pool.cc)# 查找 MySQL 库
find_package(PkgConfig REQUIRED)
pkg_check_modules(MYSQL REQUIRED mysqlclient)
# 包含 MySQL 头文件目录
include_directories(${MYSQL_INCLUDE_DIR})# 添加可执行文件
add_executable(http_request_test http_request_test.cc ${COMMON_SOURCES} ${HTTP_SOURCE} ${POOL_SOURCE})
# 链接库
target_link_libraries(http_request_test ${MYSQL_LIBRARIES})

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

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

相关文章

计算机操作系统(四) 操作系统的结构与系统调用

计算机操作系统&#xff08;四&#xff09; 操作系统的结构与系统调用 前言一、操作系统的结构1.1 简单结构1.2 模块化结构1.3 分层化结构1.4 微内核结构1.5 外核结构 二、系统调用1.1 系统调用的基本概念1.2 系统调用的类型 总结&#xff08;核心概念速记&#xff09;&#xf…

LLM之RAG理论(十四)| RAG 最佳实践

RAG 的过程很复杂&#xff0c;包含许多组成部分。我们如何确定现有的 RAG 方法及其最佳组合&#xff0c;以确定最佳 RAG 实践&#xff1f; 论文 《Searching for Best Practices in Retrieval-Augmented Generation》给出了回答。 本文将从以下三方面进行介绍&#xff1a; 首先…

利用knn算法实现手写数字分类

利用knn算法实现手写数字分类 1.作者介绍2.KNN算法2.1KNN&#xff08;K-Nearest Neighbors&#xff09;算法核心思想2.2KNN算法的工作流程2.3优缺点2.4 KNN算法图示介绍 3.实验过程3.1安装所需库3.2 MNIST数据集3.3 导入手写数字图像进行分类3.4 完整代码3.5 实验结果 1.作者介…

好吧好吧,看一下达梦的模式与用户的关系

单凭个人感觉&#xff0c;模式在达梦中属于逻辑对象合集&#xff0c;回头再看资料 应该是一个用户可以对应多个模式 问题来了&#xff0c;模式的ID和用户的ID一样吗&#xff1f; 不一样 SELECT USER_ID,USERNAME FROM DBA_USERS WHERE USERNAMETEST1; SELECT ID AS SCHID, NA…

python socket模块学习记录

python黑马程序员 通过python内置socket模块&#xff0c;在电脑本地开发一个服务器&#xff0c;一个客户端&#xff0c;连接后进行连续的聊天。服务器和客户端均可输入exit&#xff0c;主动退出连接。 服务器开发.py import socket# 创建Socket对象 socket_server socket.s…

chap1:统计学习方法概论

第1章 统计学习方法概论 文章目录 第1章 统计学习方法概论前言章节目录导读 实现统计学习方法的步骤统计学习分类基本分类监督学习无监督学习强化学习 按模型分类概率模型与非概率模型 按算法分类按技巧分类贝叶斯学习核方法 统计学习方法三要素模型模型是什么? 策略损失函数与…

爬虫案例-爬取某站视频

文章目录 1、下载FFmpeg2、爬取代码3、效果图 1、下载FFmpeg FFmpeg是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。 点击下载: ffmpeg 安装并配置 FFmpeg 步骤&#xff1a; 1.下载 FFmpeg&#xff1a; 2.访问 FFmpeg 官网。 3.选择 Wi…

车载以太网网络测试-22【传输层-DOIP协议-5】

目录 1 摘要2 DoIP时间参数2.1 ISO 13400定义的时间参数2.2 参数示例 3 DoIP节点内部状态机4 UDSonIP概述5 总结 1 摘要 本文继续对DOIP协议进行介绍&#xff0c;主要是DOIP相关的时间参数、时间参数定义以及流程示例。推荐大家对上文专题进行回顾&#xff0c;有利于系统性学习…

(论文总结)思维链激发LLM推理能力

研究背景&动机 背景:扩大模型规模已被证实具有提升模型性能和模型效率的功效&#xff0c;但是LLM对于完成推理、算术任务仍有较大不足。 动机:从之前的应用和研究中得知&#xff0c;可以用生成自然语言解释、使用神经符号等形式语言的方法来提高大模型的算术推理能力&…

anythingLLM结合searXNG实现联网搜索

1、docker-compose 部署searXNG GitHub - searxng/searxng-docker: The docker-compose files for setting up a SearXNG instance with docker. cd /usr/local git clone https://github.com/searxng/searxng-docker.git cd searxng-docker 2、修改 .env文件 # By default…

ArkUI-List组件

列表是一个复杂的容器&#xff0c;当列表项达到一定数量&#xff0c;使得列表内容超出其范围的时候&#xff0c;就会自动变为可以滚动。列表适合用来展现同类数据类型。 List的基本使用方法 List组件的构建声明是这个样子的 List(value?: {space?:number | string, initial…

Ubuntu实时读取音乐软件的音频流

文章目录 一. 前言二. 开发环境三. 具体操作四. 实际效果 一. 前言 起因是这样的&#xff0c;我需要在Ubuntu中&#xff0c;实时读取正在播放音乐的音频流&#xff0c;然后对音频进行相关的处理。本来打算使用的PipewireHelvum的方式实现&#xff0c;好处是可以直接利用Helvum…

【TI MSPM0】Timer学习

一、计数器 加法计数器&#xff1a;每进入一个脉冲&#xff0c;就加一减法计算器&#xff1a;每进入一个脉冲&#xff0c;就减一 当计数器减到0&#xff0c;触发中断 1.最短计时时间 当时钟周期为1khz时&#xff0c;最短计时时间为1ms&#xff0c;最长计时时间为65535ms 当时…

从WebRTC到嵌入式:EasyRTC如何借助大模型提升音视频通信体验

随着人工智能技术的快速发展&#xff0c;WebRTC与大模型的结合正在为音视频通信领域带来革命性的变革。WebRTC作为一种开源实时通信技术&#xff0c;以其低延迟、跨平台兼容性和强大的音视频处理能力&#xff0c;成为智能硬件和物联网设备的重要技术支撑。 而EasyRTC作为基于W…

自由学习记录(45)

顶点片元着色器&#xff08;important&#xff09; 1.需要在Pass渲染通道中编写着色器逻辑 2.可以使用cG或HLSL两种shader语言去编写Shader逻辑 3.代码量较多&#xff0c;灵活性较强&#xff0c;性能消耗更可控&#xff0c;可以实现更多渲染细节 4.适用于光照处理较少&#xf…

Quartus + VScode 实现模块化流水灯

文章目录 一、通过VScode编写Verilog代码二、模块化编程三、代码示例 一、通过VScode编写Verilog代码 1、下载Vscode 2、下载相关插件 搜索Verilog就会弹出有如图所示的插件&#xff0c;下载并安装 3、创建Quartus项目 4、创建完成后点击Tools&#xff0c;选择Options 然后在…

tryhackme——The Lay of the Land

文章目录 一、网络基础设施1.1 内网1.2 DMZ区1.3 网络枚举&#xff08;Network Enumeration&#xff09; 二、域环境三、用户和组管理四、安全解决方案4.1 基于主机的安全解决方案4.1.1 防病毒软件4.1.2 Microsoft Windows Defender4.1.3 主机防火墙4.1.4 安全事件记录与监控4.…

STM32---FreeRTOS消息队列

一、简介 1、队列简介&#xff1a; 队列&#xff1a;是任务到任务&#xff0c;任务到中断、中断到任务数据交流的一种机制&#xff08;消息传递&#xff09;。 FreeRTOS基于队列&#xff0c;实现了多种功能&#xff0c;其中包括队列集、互斥信号量、计数型信号量、二值信号量…

2025年了,5G还有三个新变化

最近舆论开始讨论5G为什么不火了&#xff1f;5G是不是停滞发展了。 实际上&#xff0c;5G不仅在发展&#xff0c;还迎来了它的升级版5G-A。 在今年西班牙举行的世界移动通信大会上&#xff0c;5G-A就是焦点之一。 被誉为全球通信领域风向标的MWC&#xff0c;汇聚了华为、中兴通…

SQLMesh SCD-2 时间维度实战:餐饮菜单价格演化追踪

场景背景&#xff1a;动态菜单价格管理 考虑某连锁餐厅的菜单管理系统&#xff0c;需要记录食品价格的历史变更轨迹。业务需求包括&#xff1a; 记录每次价格调整的时间点支持历史价格查询&#xff08;如"2020年1月2日汉堡多少钱"&#xff09;维护当前有效价格清单…