Linux網絡-------3.應?層協議HTTP

1.HTTP協議

雖然我們說,應?層協議是我們程序猿??定的.但實際上,已經有?佬們定義了?些現成的,??常好?的應?層協議,供我們直接參考使?.HTTP(超?本傳輸協議)就是其中之?。

在互聯?世界中,HTTP(HyperText Transfer Protocol,超?本傳輸協議) 是?個?關重要的協議。

它定義了客?端(如瀏覽器)與服務器之間如何通信,以交換或傳輸超?本(如HTML?檔)。HTTP協議是客?端與服務器之間通信的基礎。客?端通過HTTP協議向服務器發送請求,服務器收到請求后處理并返回響應。HTTP協議是?個?連接、?狀態的協議,即每次請求都需要建?新的連接,且服務器不會保存客?端的狀態信息。

在這里插入圖片描述

3.HTTP回應—Response

在這里插入圖片描述

4.HTTP request----------------客戶端如何打開想要訪問的資源

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

  • 左邊就是http協議規定的傳輸的數據類型,右邊則是各個主機中存儲的數據
  • 這里只用請求做說明-------說白了就是,左邊到右邊就是反序列化,右邊到左邊就是序列化!!!!!!!!!!

5.HTTP狀態碼

在這里插入圖片描述

  • 從客戶端讀取之后,需要設置狀態碼!!!!!!!

在這里插入圖片描述

  • 404就是典型的客戶端錯誤碼,指客戶訪問了服務器端沒有存儲的網頁,會顯示這個錯誤

以淘寶·網頁舉例,淘寶的服務端沒有存儲a.html 所以會顯示無法訪問!!!!!
在這里插入圖片描述

6.HTTP常??法

在這里插入圖片描述

1.GET方法

?途:?于請求URL指定的資源。
?例: GET /index.html HTTP/1.1
特性:指定資源經服務器端解析后返回響應內容。

GET方法詳解

2.POST?法

?途:?于傳輸實體的主體,通常?于提交表單數據。
?例: POST /submit.cgi HTTP/1.1
特性:可以發送?量的數據給服務器,并且數據包含在請求體中。

使用方法

二者對比------以login.html為例

在這里插入圖片描述

那如果把post改為get呢?

在這里插入圖片描述

  • 使用get的話,服務端就能拿到登錄的數據了,聯系數據庫,就能做客戶注冊了!!!!!!!!!!!
  • 使用?做分割符!!!!!!!!

在這里插入圖片描述

7.代碼全覽

先看一下格式:

在這里插入圖片描述
Http.hpp:

// 防止頭文件被重復包含
#pragma once// 包含必要的頭文件
#include "Socket.hpp"       // Socket相關功能
#include "TcpServer.hpp"    // TCP服務器實現
#include "Util.hpp"         // 工具函數
#include "Log.hpp"          // 日志模塊
#include <iostream>         // 標準輸入輸出
#include <string>           // 字符串處理
#include <memory>           // 智能指針
#include <sstream>          // 字符串流
#include <functional>       // 函數對象
#include <vector>           // 動態數組
#include <unordered_map>    // 哈希表// 使用命名空間
using namespace SocketModule;  // Socket模塊命名空間
using namespace LogModule;     // 日志模塊命名空間// 定義常量字符串
const std::string gspace = " ";        // 空格
const std::string glinespace = "\r\n"; // HTTP換行符
const std::string glinesep = ": ";     // 頭部字段分隔符// 定義Web根目錄和默認頁面
const std::string webroot = "./wwwroot";   // 網站根目錄
const std::string homepage = "index.html"; // 默認首頁
const std::string page_404 = "/404.html";  // 404頁面路徑// HTTP請求類
class HttpRequest
{
public:// 構造函數,初始化交互標志為falseHttpRequest() : _is_interact(false){}// 序列化方法(暫未實現)std::string Serialize(){return std::string();}// 解析請求行(如 GET / HTTP/1.1)void ParseReqLine(std::string &reqline){// 使用字符串流分割請求行std::stringstream ss(reqline);ss >> _method >> _uri >> _version; // 分別提取方法、URI和版本--------以空格為分隔符--------這里method是GET,uri是/--但會被自動翻譯為/下的第一個.html文件,verson則是HTTP/1.1}// 反序列化HTTP請求bool Deserialize(std::string &reqstr){// 1. 提取請求行std::string reqline;bool res = Util::ReadOneLine(reqstr, &reqline, glinespace);//把第一行讀入reqline,glinespace是\r\n-----作為一句的尾部LOG(LogLevel::DEBUG) << reqline;  // 記錄請求行日志// 2. 解析請求行ParseReqLine(reqline);// 處理URIif (_uri == "/")_uri = webroot + _uri + homepage; // 默認首頁路徑else_uri = webroot + _uri; // 其他資源路徑// 記錄解析結果日志LOG(LogLevel::DEBUG) << "_method: " << _method;LOG(LogLevel::DEBUG) << "_uri: " << _uri;LOG(LogLevel::DEBUG) << "_version: " << _version;// 檢查URI中是否包含參數const std::string temp = "?";auto pos = _uri.find(temp);if (pos == std::string::npos){return true;  // 無參數直接返回//----------訪問.html,png等靜態內容時就會直接返回!!!!!!!!!}// 分離參數和URI_args = _uri.substr(pos + temp.size()); // 提取參數部分_uri = _uri.substr(0, pos);            // 提取純URI部分_is_interact = true;                   // 標記為交互請求return true;}// 獲取URIstd::string Uri(){return _uri;}// 檢查是否為交互請求bool isInteract(){ return _is_interact;}// 獲取參數std::string Args(){return _args;}// 析構函數~HttpRequest(){}private:std::string _method;    // HTTP方法(GET/POST等)std::string _uri;       // 請求資源路徑std::string _version;   // HTTP版本std::unordered_map<std::string, std::string> _headers; // 請求頭std::string _blankline; // 空行std::string _text;      // 請求體std::string _args;      // 請求參數bool _is_interact;      // 是否為交互請求標志
};// HTTP響應類
class HttpResponse
{
public:// 構造函數,初始化空行和HTTP版本HttpResponse() : _blankline(glinespace), _version("HTTP/1.0"){}// 序列化HTTP響應std::string Serialize(){// 構建狀態行std::string status_line = _version + gspace + std::to_string(_code) + gspace + _desc + glinespace;// 構建響應頭std::string resp_header;for (auto &header : _headers){std::string line = header.first + glinesep + header.second + glinespace;resp_header += line;}// 組合狀態行、響應頭、空行和響應體return status_line + resp_header + _blankline + _text;}// 設置目標文件void SetTargetFile(const std::string &target){_targetfile = target;}// 設置狀態碼和描述void SetCode(int code){_code = code;switch (_code){case 200:_desc = "OK";break;case 404:_desc = "Not Found";break;case 301:_desc = "Moved Permanently";break;case 302:_desc = "See Other";break;default:break;}}// 添加響應頭void SetHeader(const std::string &key, const std::string &value){auto iter = _headers.find(key);if (iter != _headers.end())return;_headers.insert(std::make_pair(key, value));}// 根據文件后綴確定Content-Type!!!!!!!!//如果要訪問的網頁中還有其他資源如圖片,音頻。。。。。。就需要設置content-type-------可查找mine表!!!!std::string Uri2Suffix(const std::string &targetfile){// 查找最后一個點號auto pos = targetfile.rfind(".");if (pos == std::string::npos){return "text/html";  // 默認返回HTML類型}std::string suffix = targetfile.substr(pos);if (suffix == ".html" || suffix == ".htm")return "text/html";else if (suffix == ".jpg")return "image/jpeg";else if (suffix == "png")return "image/png";elsereturn "";}// 構建HTTP響應bool MakeResponse(){// 忽略favicon.ico請求if (_targetfile == "./wwwroot/favicon.ico"){LOG(LogLevel::DEBUG) << "用戶請求: " << _targetfile << "忽略它";return false;}// 處理重定向測試if (_targetfile == "./wwwroot/redir_test"){SetCode(301);SetHeader("Location", "https://www.qq.com/");return true;}// 讀取文件內容int filesize = 0;bool res = Util::ReadFileContent(_targetfile, &_text);if (!res)  // 文件不存在{_text = "";LOG(LogLevel::WARNING) << "client want get : " << _targetfile << " but not found";SetCode(404);  // 設置404狀態碼------客戶端訪問了不存在的網頁!!!!!!!_targetfile = webroot + page_404;  // filetarget指向404頁面!!!!!!!!filesize = Util::FileSize(_targetfile);Util::ReadFileContent(_targetfile, &_text);  // 讀取404頁面內容std::string suffix = Uri2Suffix(_targetfile);SetHeader("Content-Type", suffix);  // 設置Content-Type---------------注意這個一定要有,不然沒辦法鏈接到網頁SetHeader("Content-Length", std::to_string(filesize));  // 設置內容長度}else  // 文件存在{LOG(LogLevel::DEBUG) << "讀取文件: " << _targetfile;SetCode(200);  // 設置200狀態碼filesize = Util::FileSize(_targetfile);std::string suffix = Uri2Suffix(_targetfile);SetHeader("Conent-Type", suffix);//  設置Content-Type---------------注意這個內容類型一定要有,不然沒辦法鏈接到網頁SetHeader("Content-Length", std::to_string(filesize));SetHeader("Set-Cookie", "username=zhangsan;");  // 設置Cookie}return true;}// 設置響應體文本void SetText(const std::string &t){_text = t;}// 反序列化方法(暫未實現)bool Deserialize(std::string &reqstr){return true;}// 析構函數~HttpResponse() {}// 公有成員變量
public:std::string _version;  // HTTP版本int _code;             // 狀態碼std::string _desc;     // 狀態描述std::unordered_map<std::string, std::string> _headers; // 響應頭std::vector<std::string> cookie;  // Cookie集合std::string _blankline;  // 空行std::string _text;       // 響應體std::string _targetfile; // 目標文件路徑
};// 定義HTTP處理函數類型
using http_func_t = std::function<void(HttpRequest &req, HttpResponse &resp)>;// HTTP服務器類
class Http
{
public:// 構造函數,初始化TCP服務器Http(uint16_t port) : tsvrp(std::make_unique<TcpServer>(port))//《2》進一步使用port初始化TcpServer類并返回其指針---------->tcpseerver.hpp{}// 處理HTTP請求void HandlerHttpRquest(std::shared_ptr<Socket> &sock, InetAddr &client)//-----------<13>這個才是業務函數!{// 接收HTTP請求std::string httpreqstr;int n = sock->Recv(&httpreqstr);  // 接收請求數據--------<14>把客戶端發來的內容(需要反序列化)存入httpreqstrif (n > 0)  // 接收成功{std::cout << "##########################" << std::endl;std::cout << httpreqstr;  // 打印原始請求std::cout << "##########################" << std::endl;// 解析請求HttpRequest req;HttpResponse resp;req.Deserialize(httpreqstr);// 處理交互請求if (req.isInteract()){// 檢查路由是否存在------if (_route.find(req.Uri()) == _route.end())//查看uri是否存在于<6>中建立的_route{// 可添加重定向邏輯}else//如果存在------本文中,如果你在網頁中點擊login界面時會走這一條路!!!!!!!{// 調用注冊的處理函數_route[req.Uri()](req, resp);//-----------------------------<15>調用<6>傳遞的鍵值對的函數--即業務函數----見main.cc的Login(HttpRequest &req, HttpResponse &resp)函數std::string response_str = resp.Serialize();//序列化,準備返回給服務器sock->Send(response_str);  // 發送響應-----------------------<16>最后一步,返回給服務器!!!!!!}}else  // 處理靜態資源請求-----例如.html/.png文件{resp.SetTargetFile(req.Uri());if (resp.MakeResponse())  // 構建響應成功{std::string response_str = resp.Serialize();sock->Send(response_str);  // 發送響應}}}// 調試模式下的處理
#ifdef DEBUGstd::string httpreqstr;sock->Recv(&httpreqstr);std::cout << httpreqstr;// 構建簡單響應HttpResponse resp;resp._version = "HTTP/1.1";resp._code = 200;resp._desc = "OK";std::string filename = webroot + homepage;bool res = Util::ReadFileContent(filename, &(resp._text));(void)res;std::string response_str = resp.Serialize();sock->Send(response_str);
#endif}// 啟動HTTP服務器void Start()//---------------------<8>調用TcpServer的start,并傳遞參數是提供服務時用的fd建立的sock類,和客戶傳遞過來的主機地址--------->tcpserver.hpp{tsvrp->Start([this](std::shared_ptr<Socket> &sock, InetAddr &client){ this->HandlerHttpRquest(sock, client); });//業務函數在這呢!!!!!!}// 注冊服務路由void RegisterService(const std::string name, http_func_t h)//<7>注冊服務路由{std::string key = webroot + name; // 構建完整路徑auto iter = _route.find(key);if (iter == _route.end())  // 防止重復注冊{_route.insert(std::make_pair(key, h));}}// 析構函數~Http(){}private:std::unique_ptr<TcpServer> tsvrp;  // TCP服務器實例std::unordered_map<std::string, http_func_t> _route;  // 路由表
};

Main.cc:

#include"Http.hpp"void Login(HttpRequest &req, HttpResponse &resp)
{// req.Args();LOG(LogLevel::DEBUG) << req.Args() << ", 我們成功進入到了處理數據的邏輯";std::string text = "hello: " + req.Args(); // username=zhangsan&passwd=123456// 登錄認證resp.SetCode(200);resp.SetHeader("Content-Type","text/plain");resp.SetHeader("Content-Length", std::to_string(text.size()));resp.SetText(text);
}
// void Register(HttpRequest &req, HttpResponse &resp)
// {
//     LOG(LogLevel::DEBUG) << req.Args() << ", 我們成功進入到了處理數據的邏輯";
//     std::string text = "hello: " + req.Args();//     resp.SetCode(200);
//     resp.SetHeader("Content-Type","text/plain");
//     resp.SetHeader("Content-Length", std::to_string(text.size()));
//     resp.SetText(text);
// }
// void VipCheck(HttpRequest &req, HttpResponse &resp)
// {
//     LOG(LogLevel::DEBUG) << req.Args() << ", 我們成功進入到了處理數據的邏輯";
//     std::string text = "hello: " + req.Args();
//     resp.SetCode(200);
//     resp.SetHeader("Content-Type","text/plain");
//     resp.SetHeader("Content-Length", std::to_string(text.size()));
//     resp.SetText(text);
// }// void Search(HttpRequest &req, HttpResponse &resp)
// {// }// http port
int main(int argc, char *argv[])
{if(argc != 2){std::cout << "Usage: " << argv[0] << " port" << std::endl;exit(USAGE_ERR);}uint16_t port = std::stoi(argv[1]);std::unique_ptr<Http> httpsvr = std::make_unique<Http>(port);//《1》初始化一個HTTP類,并返回其指針---------》http.hpphttpsvr->RegisterService("/login", Login); // <6> 注冊服務路由-------->http.hpp,再回到main.cc// httpsvr->RegisterService("/register", Register);// httpsvr->RegisterService("/vip_check", VipCheck);// httpsvr->RegisterService("/s", Search);// httpsvr->RegisterService("/", Login);httpsvr->Start();//<7>開始接收服務--------->http.hppreturn 0;
}

Util.hpp:

// 防止頭文件重復包含的編譯指令
#pragma once// 包含標準輸入輸出流庫
#include <iostream>
// 包含文件流操作庫
#include <fstream>
// 包含字符串處理庫
#include <string>// 工具類聲明
class Util
{
public:// 靜態方法:讀取文件內容到字符串中,傳遞一個文件路徑,和一個string,把文件的內容讀取到string中// 參數:filename - 文件名,out - 輸出字符串指針// 返回值:成功返回true,失敗返回falsestatic bool ReadFileContent(const std::string &filename /*std::vector<char>*/, std::string *out){// 獲取文件大小int filesize = FileSize(filename); // FileSize函數用于獲取指定文件的大小(以字節為單位)。如果沒打開就返回-1!!!!// 檢查文件大小是否有效if (filesize > 0){// 創建輸入文件流對象std::ifstream in(filename); // ifstream#include <fstream>// 方式1:先聲明后打開// std::ifstream in;          // 創建未關聯文件的流對象// in.open("example.txt");    // 打開文件// 方式2:聲明時直接打開(推薦)// std::ifstream in("example.txt");  // 創建并立即打開文件,不用顯示調用open函數打開文件// 檢查文件是否成功打開if (!in.is_open())return false;// 調整輸出字符串大小以容納文件內容out->resize(filesize);// 將文件內容讀取到字符串中// 注意:這里使用了c_str()獲取字符串底層指針,并進行強制類型轉換in.read((char *)(out->c_str()), filesize);// istream& read(char* s, streamsize n);// 在 C++ 中,out->c_str() 返回的是 const char* 類型指針,而 std::ifstream::read() 需要的是 char* 類型指針,因此需要進行強制類型轉換。// 關閉文件流in.close(); // 記得要關閉!!!}else{// 文件大小為0或獲取失敗時返回falsereturn false;}// 讀取成功返回truereturn true;}// 靜態方法:從大字符串中讀取一行// 參數:bigstr - 輸入大字符串,out - 輸出行字符串指針,sep - 行分隔符// 返回值:成功返回true,失敗返回falsestatic bool ReadOneLine(std::string &bigstr, std::string *out, const std::string &sep /*\r\n*/){// 查找分隔符位置auto pos = bigstr.find(sep);// 如果沒有找到分隔符則返回falseif (pos == std::string::npos) // std::string::npos 是 C++ 標準庫中 std::string 類的一個靜態常量成員,表示"未找到"或"無效位置"的特殊值。它是字符串操作中非常重要的一個標記值。return false;// 提取分隔符前的內容作為一行*out = bigstr.substr(0, pos); // 起始永遠是0// 從原字符串中刪除已讀取的行和分隔符bigstr.erase(0, pos + sep.size()); // 起始必須是0// 讀取成功返回truereturn true;}// 靜態方法:獲取文件大小// 參數:filename - 文件名// 返回值:成功返回文件大小(字節),失敗返回-1static int FileSize(const std::string &filename){// 以二進制模式打開文件std::ifstream in(filename, std::ios::binary); // std::ios::binary 是 C++ 中文件打開模式的一個標志,它的作用是告訴文件流以二進制模式而非文本模式打開文件// 文本模式(默認):// 在某些系統(如 Windows)上,會進行換行符轉換:// 讀取時,\r\n(Windows 換行)會被轉換為 \n(C++ 標準換行)。// 寫入時,\n 會被轉換為 \r\n。// 可能在某些平臺上處理特殊字符(如 EOF)時會有額外行為。// 二進制模式:// 完全按原樣讀寫數據!!!!!,不做任何轉換。// 適合處理非文本文件(如圖片!!!!!!!、音頻、視頻、壓縮包等)。!!!!!!!!!!!!!!!!!!!!!!!// 也適合需要精確控制文件內容的場景(如跨平臺數據交換)。// 檢查文件是否成功打開if (!in.is_open())return -1;// 將文件指針移動到文件末尾--------seekg移動函數!!!!in.seekg(0, in.end);//in.end:基準位置(seek direction),這里是文件末尾(std::ios::end)。// 獲取當前指針位置(即文件大小)int filesize = in.tellg();// 將文件指針移回文件開頭in.seekg(0, in.beg);// 關閉文件流in.close();// 返回文件大小return filesize;}
}; // 類定義結束

效果演示

在這里插入圖片描述
在這里插入圖片描述

  • 在瀏覽器中輸入115.120.238.130:8081
  • 別忘了要先去云服務器官網開啟安全組,這樣瀏覽器才能訪問服務端

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/91375.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/91375.shtml
英文地址,請注明出處:http://en.pswp.cn/web/91375.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

05 GWAS表型數據處理原理

表型數據處理 ? 質量性狀 – 二分類&#xff1a;可用0 / 1, 1 / 2 數值表示 – 多分類&#xff1a;啞變量賦值&#xff0c;0/1 ? 數量性狀 – 盡量符合正太分布 – 剔除異常表型值樣本 – 多年多點重復觀測 – 對于閾值性狀&#xff0c;分級數量化或啞變量賦值 R中 shapiro.t…

【Cpolar實現內網穿透】

Cpolar實現內網穿透業務需求第一步&#xff1a;準備工作1、關閉安全軟件2、下載所需軟件第二步&#xff1a;Nginx的配置第三步&#xff1a;使用cpolar實現內網穿透1、進入 https://dashboard.cpolar.com/get-started 注冊&#xff0c;登錄&#xff0c;完成身份證的實名認證2、下…

基于 JavaWeb+MySQL 的學院黨費繳費系統

基于 JavaWeb 的學院黨費繳費系統第 1 章緒論1.1 項目背景當今互聯網發展及其迅速&#xff0c;互聯網的便利性已經遍及到各行各業&#xff0c;惠及到每一個人&#xff0c;傳統的繳費方式都需要每個人前往繳費點陸續排隊繳費&#xff0c;不僅浪費大量了個人時間&#xff0c;而且…

LCGL基本使用

LVGC簡介 light video Graphics Library (1)純c與語言編程,將面向對象的思想植入c語言。 (2)輕量化圖形庫資源,人機交互效果好,在(ios Android QT)移植性較好,但是這些平臺對硬件要求較高 lcgc工程搭建 工程源碼的獲取 獲取工程結構 https://github.com/lvgl/lv_po…

嵌入式第十六課!!!結構體與共用體

一、結構體結構體是一種數據類型&#xff0c;它的形式是這樣的&#xff1a;struct 結構體名{ 結構體成員語句1&#xff1b;結構體成員語句2&#xff1b;結構體成員語句3&#xff1b;}&#xff1b;舉個例子&#xff1a;struct Student {int id;char name[20];float score…

java web 實現簡單下載功能

java web 實現簡單下載功能 項目結構├── src\ │ ├── a.txt │ └── com\ │ └── demo\ │ └── web\ │ ├── Cookie\ │ ├── download\ │ ├── homework\ │ ├── serv…

虛幻基礎:模型穿模

能幫到你的話&#xff0c;就給個贊吧 &#x1f618; 文章目錄模型穿模模型之間的阻擋是否正確設置模型是角色的組件&#xff1a;角色的組件不會與場景中其他的物體發生阻擋但可以發生重疊模型穿模 模型之間的阻擋是否正確設置 模型是角色的組件&#xff1a;角色的組件不會與場…

【Linux】linux基礎開發工具(二) 編譯器gcc/g++、動靜態庫感性認識、自動化構建-make/Makefile

文章目錄一、gcc/g介紹二、gcc編譯選項預處理編譯匯編鏈接三個細節三、動靜態庫感性認識動靜態庫的優缺點四、自動化構建-make/Makefile背景知識初步上手Makefilemakefile的推導過程makefile語法一、gcc/g介紹 我們之前介紹了編輯器vim&#xff0c;可以讓我們在linux上linux系統…

CentOS 7 上使用 Docker 安裝 Jenkins 完整教程

目錄 前言 準備工作 系統要求 檢查系統信息 更新系統 安裝Docker 第一步:卸載舊版本Docker(如果存在) 第二步:安裝必要的軟件包 第三步:添加Docker官方倉庫 第四步:安裝Docker CE 第五步:啟動Docker服務 第六步:驗證Docker安裝 第七步:配置Docker用戶權限…

30.【.NET8 實戰--孢子記賬--從單體到微服務--轉向微服務】--單體轉微服務--公共代碼--用戶上下文會話

在前面的文章中&#xff0c;我們會看到使用ContextSession來獲取當前用戶的UserId和UserName。這篇文章我們就一起來看看如何實現ContextSession。 一、ContextSession的實現 我們在公共類庫SP.Common中創建一個名為ContextSession的類&#xff0c;用于獲取當前請求的用戶信息。…

BaseDao

#### 10.1 DAO概念> DAO&#xff1a;Data Access Object&#xff0c;數據訪問對象。 > > Java是面向對象語言&#xff0c;數據在Java中通常以對象的形式存在。一張表對應一個實體類&#xff0c;一張表的操作對應一個DAO對象&#xff01;>> 在Java操作數據庫時&a…

USRP捕獲手機/路由器數據傳輸信號波形(中)

目錄&#xff1a; USRP捕獲手機/路由器數據傳輸信號波形&#xff08;上&#xff09; USRP捕獲手機/路由器數據傳輸信號波形&#xff08;中&#xff09; USRP捕獲手機/路由器數據傳輸信號波形&#xff08;下&#xff09; 三、雙工通信信號捕獲 3.1 信號接收系統 5805e6Hz&a…

使用 Kiro AI IDE 3小時實現全棧應用Admin系統

Hello&#xff0c; 大家好&#xff0c;我是程序員海軍, 全棧開發 |AI愛好者 &#xff5c; 獨立開發。 之前我是采用Node生態開發的大模型以及MCP Server,大模型開發的生態主要是Python語言&#xff0c;為了更好的學習大模型開發&#xff0c;于是開了新坑。開始學習Python, 以及…

瀏覽器pdf、image顯示

瀏覽器地址欄 pdf data:application/pdf;base64, data:application/pdf;base64,JVBERi0xLjcKJeLjz9MKMjMgMCBvYmoKPDwv image data:image/jpeg;base64, data:image/jpeg;base64,/9j/4Q3fRXhpZgAATU0AKgAAAAgABwE

《Linux運維總結:銀河麒麟V10 SP3啟動docker容器報錯permission denied》

總結&#xff1a;整理不易&#xff0c;如果對你有幫助&#xff0c;可否點贊關注一下&#xff1f; 更多詳細內容請參考&#xff1a;Linux運維實戰總結 一、環境信息 二、背景 1、使用docker啟動一個nginx容器&#xff0c;報錯信息如下&#xff1a; docker: Error response from…

PDF源碼解析

PDF源碼解析打開PDF解析PDF?0. 文件頭關鍵信息解析技術原理圖解文件頭的重要性實際文件結構示例開發者注意事項歷史背景1. 根目錄整體結構關鍵字段解析核心概念解釋實際應用場景完整對象關系圖技術總結2. 頁面樹對象結構關鍵字段解析頁面樹工作原理技術要點總結實際應用3. 圖像…

java開閉原則 open-closed principle

基本知識 1.核心思想&#xff1a;面向抽象編程 2.基本內涵&#xff1a;對修改關閉&#xff0c;對擴展開放 3.要求&#xff1a;盡可能不修改源碼而是增加新功能 例子 以spring5核心原理與30個類手寫實戰中的為例 package com.gupaoedu.vip.design.principle.openclose;/*** Crea…

擁抱智慧物流時代:數字孿生技術的應用與前景

概述 在數字經濟全面推進的當下&#xff0c;物流行業正經歷著前所未有的智能化升級。作為新一代信息技術的重要代表&#xff0c;數字孿生技術正悄然改變著物流的運作方式和決策模式。所謂數字孿生&#xff0c;是指在虛擬空間中創建與現實物流系統高度一致的數字模型&#xff0…

libnest2d-頭文件分析-libnest2d.hpp-幾何類型-策略類型-參數配置

libnest2d 庫的主頭文件&#xff0c;定義了一個用于 二維不規則形狀自動排樣&#xff08;Nesting&#xff09; 的C接口。以下是詳細解析&#xff1a;1. 頭文件結構 (1) 防止重復包含 #ifndef LIBNEST2D_HPP #define LIBNEST2D_HPP // ... #endif // LIBNEST2D_HPP確保頭文件只被…

【Docker】部署Docker可視化管理面板Dpanel

一、DPanel 介紹 1.1 DPanel 簡介 DPanel 是一款專為 Docker 設計的可視化管理面板&#xff0c;旨在降低容器、鏡像及相關資源的管理門檻。通過簡潔直觀的圖形化界面&#xff0c;即使是對 Docker 不熟悉的用戶&#xff0c;也能輕松上手&#xff0c;實現容器化應用的高效部署與管…