当前位置: 首页 > news >正文

Linux之Http协议分析以及cookie和session

Linux之Http协议分析以及cookie和session

  • 一.分析请求行与响应行
    • 1.1请求行
    • 1.1.1资源的URL路径
    • 1.1.2常见的方法
    • 1.2响应行
  • 二.cookie和session
    • 2.1cookie
    • 2.2session

一.分析请求行与响应行

在我们简单了解了请求和响应的格式以及模拟实现了请求和响应后我们已经可以通过网页来访问我们的服务器从而获得一些简单的信息,但是这些还只是http协议的冰山一角,今天我们还需要继续分析请求和响应中的首行从而来更了解http协议。

1.1请求行

请求行中一共分为三部分:方法+URL路径+版本号。其中版本号我们在上篇文章中已经谈过其中的内容也相对来说不那么重要,而方法我们也只要会用最常见的两种以及记住其余的大致作用即可但是URL路径却是我们最需要谈的。

1.1.1资源的URL路径

我们先来再看一下我们的请求行中存储的URL路径
在这里插入图片描述
这里的我只用了IP:端口号的方式在浏览器上访问服务器而这时URl路径显示的就只是一个/符号那么如果我在IP:端口号的基础上加上路径呢?那时候请求行中的URL路径会发生改改变吗?
在这里插入图片描述
我将路径改成了/a/b后很明请求行中的URL路径也发生了改变,就说明如果我们访问时在端口后不加上路径那么就会默认访问/路径下的资源,如果自己添加了路径就会访问该路径下的资源。可是问题是这个/是什么呢?为什么不添加路径就会默认访问该路径下的资源?

http协议规定的是如果我们不自己添加访问的路径,那么就会默认访问web根目录而web根目录通俗一点的话就是访问网址的首页那么具体是访问根目录下的哪个资源呢?其实我们默认访问的是/index.html。
可能大家会说我们模拟实现的代码里并没有什么index.html资源啊而且你说自己填路径和访问web根目录时访问的资源是不一样的那么为什么我们上面的图片里都是一样的helloworld呢?这是我们编写的代码的缘故我们现在并没有对URL路径加以分析而且一股脑的对于访问都塞一个一样的响应回去所以导致如此结果。

那么我们要如何区分URL路径而且那些不同路径下的资源又要怎么存放呢?
在Linux中一切皆文件所以大家很容易可以想到我们可以创建几个不同的文件来存放资源到时候只要我们对URL路径进行分析再让其去访问其中的内容即可。所以我们可以创建一共目录来存放这些不同路径下的资源,而这个目录在网络编程下一般都是设为wwwroot也可以是webroot。接下来我就来给大家模拟实现一下我们所说的这个方法。

// HttpProtocol.hpp
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>const static std::string HttpSep = "\r\n";// 默认访问的资源
const static std::string homepage = "index.html";
const static std::string wwwroot = "./wwwroot";class HttpRequest
{
public:HttpRequest(): _blankline(HttpSep), _path(wwwroot){}~HttpRequest(){}bool Getline(std::string &request, std::string *line){// 请求行\r\n请求报头\r\n空行\r\n请求正文// 在请求中查找HttpSepauto pos = request.find(HttpSep);if (pos == std::string::npos){return false;}// 分割请求*line = request.substr(0, pos);request.erase(0, pos + HttpSep.size());return true;}bool Deserializa(std::string &request){std::string line;// 判断是否只有请求行bool ok = Getline(request, &line);if (!ok){return false;}_req_line = line;// 一行一行的分割请求while (true){bool ok = Getline(request, &line);if (ok && line.empty()){// 如果分割行成功并且line中存储是空行// 说明request只剩下了正文(无论正文是否有内容)_req_content = request;break;}else if (ok && !line.empty()){// 如果分割成功并且line内有内容// 说明line中存储的是请求报头中的一行_req_header.push_back(line);}else{break;}}return true;}void DebugHttp(){std::cout << "_req_line:" << _req_line << std::endl;std::cout << "_req_header:" << std::endl;for (auto &line : _req_header){std::cout << "---> " << line << std::endl;}std::cout << "_req_blank: " << _blankline << std::endl;std::cout << "_req_content: " << _req_content << std::endl;std::cout << "Method: " << _method << std::endl;std::cout << "url: " << _url << std::endl;std::cout << "path: " << _path << std::endl;std::cout << "http_version: " << _http_version << std::endl;}// 分析请求行void AnalyseReqline(){// 大家可以用find来查找空格之后再进行分割的方法// 但是我这里就使用C++中专门处理字符串的输入输出流stringstream// 使用sstream需要包含头文件<sstream>std::stringstream ss(_req_line);// 请求行:method path version// 而stringstream的插入会自动以空格为分割ss >> _method >> _url >> _http_version;// 如果_url为根目录就还需要添加默认的资源if (_url == "/"){_path += _url;_path += homepage;}else{// 不是根目录则直接加URL路径即可_path += _url;}}// 分析后缀void AnalyseSuffix(){// index.html我们只需要拿到.和其之后的字符即可auto pos = _path.rfind(".");if (pos != std::string::npos){_suffix = _path.substr(pos);}else{_suffix = ".html";}}// 对资源文件做处理std::string GetFileContentHelper(const std::string &path){// 因为是对文件做处理所以使用ifstreamstd::cout << "this1" << std::endl;std::cout << path << std::endl;std::ifstream in(path, std::ios::binary);std::cout << "this2" << std::endl;// 打开文件,失败返回""成功则读取其中内容if (!in.is_open()){std::cout << "this3" << std::endl;return "";}std::cout << "this4" << std::endl;std::string content;std::string line;// 一行一行的读取while (std::getline(in, line)){content += line;}in.close();return content;}std::string GetFileContent(){return GetFileContentHelper(_path);}void Analyse(){// 1.分析请求行AnalyseReqline();// 2.分析后缀AnalyseSuffix();}std::string GetUrl(){return _url;}std::string GetPath(){return _path;}std::string GetSuffix(){return _suffix;}private:// 根据请求格式我们可以设计出四个变量std::string _req_line;                // 请求行std::vector<std::string> _req_header; // 请求报头std::string _blankline;               // 空行std::string _req_content;             // 请求正文// 分析请求行后std::string _method;       // 方法std::string _url;          // 路径std::string _http_version; // 版本// 分析URL后将其分为路径和后缀两部分// 因为资源有很多种类所以我们需要判别资源的种类再加以不同处理std::string _path;std::string _suffix;
};
// httpserver.cc
#include <iostream>
#include <memory>#include "HttpProtocol.hpp"
#include "Tcpserver.hpp"// 文件的后缀决定了文件的类型,http协议需要响应报头中包含正文的文件类型
std::string SuffixToType(const std::string &suffix)
{if (suffix == ".html" || suffix == ".htm"){return "text/html";}else if (suffix == ".png"){return "image/png";}else if (suffix == ".jpg"){return "image/jpeg";}else{return "Unknown";}
}std::string HandleMethod(std::string request)
{HttpRequest http_req;http_req.Deserializa(request);http_req.Analyse();http_req.DebugHttp();std::string content = http_req.GetFileContentHelper(http_req.GetPath());if (!content.empty()){std::string httpstatusline = "Http/1.0 200 OK\r\n";std::string httpheader = "Content-Length: " + std::to_string(content.size()) + "\r\n"; // 正文的大小httpheader += "Content-Type: " + SuffixToType(http_req.GetSuffix()) + "\r\n";          // 正文的类型httpheader += "\r\n";std::string httpresponse = httpstatusline + httpheader + content;return httpresponse;}return "";
}int main(int argc, char *argv[])
{if (argc != 2){std::cout << "Usge:\n"<< argv[0] << " port" << std::endl;return 0;}uint16_t localport = std::stoi(argv[1]);std::unique_ptr<TcpServer> svr(new TcpServer(localport, HandleMethod));svr->Loop();return 0;
}
}

在这里插入图片描述

我们的资源有很多种类型,一般常见的就是.html,.png等等。对应.html文件的编写是我们前端人员的工作所以大家可以自行去搜索学习一下。
在这里插入图片描述

这是我们现在用浏览器访问服务器web根目录资源的样子,大家可以发现我们的图片加载不出来这是因为我们的图片在解析的时候是全二进制的但是我们如今使用的对资源文件做处理是针对于文本文件的如.html文件所以我们还需要将处理方法改进成通用方法才行。

// 对资源文件做处理std::string GetFileContentHelper(const std::string &path){// 文本//  // 因为是对文件做处理所以使用ifstream//  std::ifstream in(path, std::ios::binary);//  // 打开文件,失败返回""成功则读取其中内容//  if (!in.is_open())//  {//      return "";//  }// std::string content;// std::string line;// // 一行一行的读取// while (std::getline(in, line))// {//     content += line;// }// in.close();// return content;// 通用方法std::ifstream in(path, std::ios::binary);if (!in.is_open()){return "";}// 跳转到in的末尾in.seekg(0, in.end);// 将in的大小填入filesize中int filesize = in.tellg();// 跳转到in的开头in.seekg(0, in.beg);std::string content;// 设置content的大小content.resize(filesize);// 将in的内容填入到content中in.read((char *)content.c_str(), filesize);in.close();return content;}

在这里插入图片描述

1.1.2常见的方法

在我们了解常见的方法前我们需要先知道上网这个行为的本质是什么,本质就是我们从网上上获取资源或者我们向服务器传送参数也就是资源,而我们最常用的GET方法和POST方法就包含了这两方面。

  1. GET方法
    通常用来获取资源也可以通过URL地址来传参,但是传输的参数私密性不强。传参这个动作需要依靠我们html文件的表单来实现
    在这里插入图片描述
    那么我们向里面输入信息后URL地址会发生怎么样的变化呢?在这里插入图片描述
    那么我们如果向里面填写信息呢信息会被加入到URL里吗?
    在这里插入图片描述
    至于为什么私密性不强我想大家一眼就看出来了因为在URL地址中所有人都能看见当然私密性不强了。

  2. POST方法
    通常用来上传数据但是POST方法上传数据的形式和GET不同,POST方法不会将数据存在URL地址中而是存于请求正文中传给服务器,通过请求正文传参那么肉眼可见的POST传参的私密性会好一点。
    在这里插入图片描述

同时由于GET是利用URL传参所以会受到URL自身被规定的长度所限制但是POST方法则不会,虽然POST方法的私密性比GET方法好一点但是其实两者都不安全。那么我们想要我们传输的账号密码安全就必须经过加密和解密的过程这也就形成了我们之后的https协议。

至于其余的方法我就直接用别的博主写的来列给大家看看了因为都不是很重要

  1. HEAD
    获得报文首部,类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头。欲判断某个资源是否存在,我们通常使用GET,但这里用HEAD则意义更加明确。
    向服务器获取某些易过期或丢失大型文件时,可用HEAD方式查询资源是否存在。

  2. OPTIONS
    询问支持的方法客户端询问服务器可以提交哪些请求方法。这个方法很有趣,它用于获取当前URL所支持的方法。若请求成功,则它会在HTTP头中包含一个名为“Allow”的头,值是所支持的方法,如“GET, POST”。
    极少使用。

  3. PUT
    传输文件。从客户端向服务器传送的数据取代指定的文档的内容,即指定上传资源存放路径。这个方法比较少见。HTML表单也不支持这个。本质上来讲, PUT和POST极为相似,都是向服务器发送数据,但它们之间有一个重要区别,PUT通常指定了资源的存放位置,而POST则没有,POST的数据存放位置由服务器自己决定。

  4. PATCH
    局部更新文件,是对 PUT 方法的补充,用来对已知资源进行局部更新 。
    极少使用。

  5. DELETE
    删除文件。请求服务器删除指定的资源。
    基本上这个也很少见,不过还是有一些地方比如amazon的S3云服务里面就用的这个方法来删除资源。

  6. TRACE
    追踪路径,回显服务器收到的请求,客户端可以对请求消息的传输路径进行追踪,TRACE方法是让Web服务器端将之前的请求通信还给客户端的方法。主要用于测试或诊断。
    极少使用。

  7. CONNECT
    要求用隧道协议连接代理,HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。CONNECT方法要求在与代理服务器通信时建立隧道,实现用隧道协议进行TCP通信。主要使用SSL(安全套接层)和TLS(传输层安全)协议把通信内容加密后经网络隧道传输。
    极少使用。

原文链接:https://blog.csdn.net/demo_yo/article/details/123596028

1.2响应行

对应响应行的分析就简单多了我们只需要分析状态码即可,状态码也很好理解就是告诉你完成的情况或者有一些特殊情况。所以我直接给状态码贴给大家我拿其中比较典型的几个给大家说一说然后我们也还需要模拟实现一下不同状态码的情况。
在这里插入图片描述
一共五大类状态码分别以12345开头每大类中还需要细分,我就给每大类中典型的跟大家解释一下这样大家也对五种状态码有个概念。

  1. 信息状态码(1xx)
    信息状态码我们只需要记住100即可,100状态码出现的情况一般是当我们从客户端往服务器传输数据时过大服务器无法一次性接收完全,当服务器接收了一半之后就会传出100状态码来告诉客户端你可以继续上传数据了。所以100状态码就是继续的含义。
  2. 成功状态码(2xx)
    成功状态码我们需要记住200和204。200很简单就是告诉你请求被处理成功了而204也是告诉你请求被处理成功了但是没有结果返回。
  3. 重定向状态码(3xx)
    重定向状态码需要大家理解并且记住301和302分别是永久重定向和临时重定向。首先我们来解释一下什么是http里的重定向,我给大家举两个例子一个是当我们创建的网站过期了之后我们需要换IP地址换域名了但是用户只记得旧网站的网址另外一个是我们在各种的网站中会登入自己的账号有时候在登入账号后会自动条状到自己账号的主页。第一个需要我们在将旧网站重定向到新网站从而达成用户只要登入旧网站就会自动跳转到新网站上,第二个是如何完成的呢也就像我们刚刚展示表单时我们把登入按钮重定向到用户自己的主页上这样这要我们登入成功了就会自动跳转。从这两个例子中我们可以发现重定向的作用一般就是从一个网址跳转到另外一个网址上,并且这两个例子中的重定向还不一样第一个例子是永久重定向因为旧网站不用了过期了只用新网站现在,第二个例子是临时重定向我们只需要在当时让用户完成登入后跳转到主页即可。
  4. 客户端错误状态码(4xx)
    客户端错误状态码则需要大家记住403和404这两个即可。404状态码其实算这些状态码里比较常见的了,我们只需要访问一些不存在的网站就很容易得出这个状态码。在这里插入图片描述
    而403状态码则是我们如果访问了一些我们没有全新的网址就会出现。

这两个状态码是很好理解的但是比较难理解的是4xx状态码为什么叫做客户端错误状态码,明明是我访问你们服务器为什么变成我错了呢?其实从这两个状态码的名字里就能看出来一个是访问不存在的网址一个是访问没权限的网址,从服务器的角度上我明明有这么多页面可以给你看你偏偏找一个不存在的网址或者找一个你没权限的网址,我用心用力的给你服务你这不是给我找茬吗。所以这是用户自己作的妖当然就是客户端错误状态码了。

  1. 服务器错误状态码(5xx)
    这个状态码需要大家记住500和503,服务器错误状态码平时应该很少见因为我们如今使用的软件大多都是一些大厂发行的他们的服务器一般都是比较稳定的除了个别公司。500状态码的含义是服务器崩溃或者数据库崩溃导致页面无法加载出来,503状态码是服务器正在维护或者过载导致暂时无法处理请求。

在了解了这些状态码后我们也可以来模拟实现一下这些状态码对应的情况

const static std::string Space = " ";// 响应
class HttpResponse
{
public:HttpResponse(): _version("HTTP/1.0"), _status_code(200), _status_code_desc("OK"), _blankline(HttpSep){}~HttpResponse(){}void SetCode(int status_code){_status_code = status_code;}void SetDesc(std::string status_code_desc){_status_code_desc = status_code_desc;}void MakeStatusLine(){_status_line = _version + Space + std::to_string(_status_code) + Space + _status_code_desc;}void Addheader(std::string header){_resp_header.push_back(header);}void Addcontent(std::string content){_resp_content = content;}std::string Serializa(){std::string response_str = _status_line;for (auto header : _resp_header){response_str += header;}response_str += _blankline;response_str += _resp_content;return response_str;}private:std::string _status_line;              // 状态行std::vector<std::string> _resp_header; // 响应报头std::string _blankline;                // 空行std::string _resp_content;             // 响应正文std::string _version;          // 版本int _status_code;              // 状态码std::string _status_code_desc; // 状态码解释
};
// Tcpserver.cc
#include <iostream>
#include <memory>#include "HttpProtocol.hpp"
#include "Tcpserver.hpp"// 文件的后缀决定了文件的类型,http协议需要响应报头中包含正文的文件类型
std::string SuffixToType(const std::string &suffix)
{if (suffix == ".html" || suffix == ".htm"){return "text/html";}else if (suffix == ".png"){return "image/png";}else if (suffix == ".jpg"){return "image/jpeg";}else{return "Unknown";}
}std::string CodeToDesc(int code)
{if (code == 200){return "OK";}else if (code == 301){return "Moved Permanently";}else if (code == 307){return "Temporary Redirect";}else if (code == 403){return "Forbidden";}else if (code == 404){return "Not Found";}else if (code == 500){return "Internal Server Error";}else{return "Unknown";}
}std::string HandleMethod(std::string request)
{HttpRequest http_req;http_req.Deserializa(request);http_req.Analyse();http_req.DebugHttp();int code = 200;std::string content = http_req.GetFileContentHelper(http_req.GetPath());if (content.empty()){code = 404;content = http_req.GetFile404();}HttpResponse response;// 设置状态码response.SetCode(code);// 设置状态码描述response.SetDesc(CodeToDesc(code));// 生成状态行response.MakeStatusLine();// 插入响应报头std::string content_len_str = "Content-Length: " + std::to_string(content.size()) + "\r\n"; // 正文的大小response.Addheader(content_len_str);std::string content_type_str = "Content-Type: " + SuffixToType(http_req.GetSuffix()) + "\r\n"; // 正文的类型response.Addheader(content_type_str);// 插入响应正文response.Addcontent(content);// 序列化return response.Serializa();
}int main(int argc, char *argv[])
{if (argc != 2){std::cout << "Usge:\n"<< argv[0] << " port" << std::endl;return 0;}uint16_t localport = std::stoi(argv[1]);std::unique_ptr<TcpServer> svr(new TcpServer(localport, HandleMethod));svr->Loop();return 0;
}

二.cookie和session

我们在学习了GET和POST方法后知道我们是可以通过请求正文给服务器传输信息的从而达成登入的操作但是不知道大家在日常使用中有没有发现我们只要登入了某个网站之后的一段时间我们就不需要再输入账号密码来登入了,这是为什么呢?
我们很容易就能想到一个答案:Http协议记住了我们的账号密码这样只要我们登入过一次之后就不用再登入了。但是这是错的这是因为Http协议是无状态无连接的,什么叫做无状态无连接呢也就是Http协议是不记住自己的历史的所以每次打开一个网站理论上是都是第一次打开因为http协议不记得你之前来过那不就是当第一次吗。这个问题也就导致了理论上我们每次都需要重新登入就算我们答应网站的公司也不答应啊,这样的操作不就很花费用户的时间和耐心也就会让网站的流量下降盈利也就下降了。所以针对这种情况延申出了两种解决方法:cookie和session,准确的来说session是在cookie的基础上改进了。

2.1cookie

想要解决这个问题其实很简单我们只需要在第一次登入的时候通过POST方法将账号密码传入到服务器中之后服务器再在响应报头中添加进去返回给浏览器,这样浏览器中就存有了你的账号密码之后每次再登入对应的网址的时候浏览器只要将你的账号密码通过请求报头传入到服务器让服务器查询是否有此用户即可。而cookie就是浏览器保存起来的报头形式的账号密码。
在这里插入图片描述
但是这样的解决方案依然有问题:浏览器保存的都是我真实的私密信息但是浏览器中的信息太过容易被盗取只要有人获得了我的私密信息就可以随意使用我的账号了。这就造成了用户的隐私安全问题。
在这里插入图片描述
我们现在使用的都是https协议所以cookie都是被加密过的但是在以前只用http协议时cookie信息是明晃晃的存在浏览器中的。

2.2session

所以有人为了避免这种问题将cookie改进成了session,而改进的地方就在于当服务器接收了来自浏览器POST的数据后它会通过这个数据生成一个结构体session和一个独一无二的sessionid并且这个session中还会存放用户的状态例如地理位置等等,之后就将账号密码再传回给浏览器而是将这个sessionid传给浏览器。浏览器只需要保存这个sessionid在下次登入的时候将sessionid传给服务器,服务器再进行查找判断即可。这样的好处是浏览器保存的就不是用户的真实隐私而是一串独特的sessionid并且在session中你不仅可以通过账号密码来判断用户是否合法还可以通过用户此次登入的地理位置和上一次的地理位置的距离来判断。
在这里插入图片描述
这样就解决了用户的隐私安全问题。

相关文章:

Linux之Http协议分析以及cookie和session

Linux之Http协议分析以及cookie和session 一.分析请求行与响应行1.1请求行1.1.1资源的URL路径1.1.2常见的方法1.2响应行 二.cookie和session2.1cookie2.2session 一.分析请求行与响应行 在我们简单了解了请求和响应的格式以及模拟实现了请求和响应后我们已经可以通过网页来访问…...

Python Pandas(5):Pandas Excel 文件操作

Pandas 提供了丰富的 Excel 文件操作功能&#xff0c;帮助我们方便地读取和写入 .xls 和 .xlsx 文件&#xff0c;支持多表单、索引、列选择等复杂操作&#xff0c;是数据分析中必备的工具。 操作方法说明读取 Excel 文件pd.read_excel()读取 Excel 文件&#xff0c;返回 DataF…...

iOS主要知识点梳理回顾-3-运行时

运行时&#xff08;runtime&#xff09; 运行时是OC的重要特性&#xff0c;也是OC动态性的根本支撑。动态&#xff0c;如果利用好了&#xff0c;扩展性就很强。当然了&#xff0c;OC的动态性只能算是一个一般水平。与swift、java这种强类型校验的语言相比&#xff0c;OC动态性很…...

[渗透测试]热门搜索引擎推荐— — shodan篇

[渗透测试]热门搜索引擎推荐— — shodan篇 免责声明&#xff1a;本文仅用于分享渗透测试工具&#xff0c;大家使用时&#xff0c;一定需要遵守相关法律法规。 除了shodan&#xff0c;还有很多其他热门的&#xff0c;比如&#xff1a;fofa、奇安信的鹰图、钟馗之眼等&#xff0…...

java-初识List

List&#xff1a; List 是一个接口&#xff0c;属于 java.util 包&#xff0c;用于表示有序的元素集合。List 允许存储重复元素&#xff0c;并且可以通过索引访问元素。它是 Java 集合框架&#xff08;Java Collections Framework&#xff09;的一部分 特点&#xff1a; 有序…...

ElasticSearch集群因索引关闭重打开导致飘红问题排查

背景 某组件向 ElasticSearch 写入数据&#xff0c;从最近某一天开始写入速度变慢&#xff0c;数据一直有积压。推测是 ElasticSearch 集群压力导致的&#xff0c;查看 ElasticSearch 集群状态&#xff0c;发现集群确实处于 red 状态。 本文记录 ElasticSearch 集群因索引关闭…...

idea 如何使用deepseek 保姆级教程

1.安装idea插件codegpt 2.注册deepseek并生成apikey deepseek 开发平台&#xff1a; DeepSeek​​​​​​​ 3.在idea进行codegpt配置 打开idea的File->Settings->Tools->CodeGPT->Providers->Custom OpenAI Chat Completions的URL填写 https://api.deepseek…...

【大模型】硅基流动对接DeepSeek使用详解

目录 一、前言 二、硅基流动介绍 2.1 硅基流动平台介绍 2.1.1 平台是做什么的 2.2 主要特点与功能 2.2.1 适用场景 三、硅基流动快速使用 3.1 账户注册 3.2 token获取 3.2.1 获取token技巧 四、Cherry-Studio对接DeepSeek 4.1 获取 Cherry-Studio 4.2 Cherry-Stud…...

机器学习数学基础:14.矩阵的公式

1. 操作顺序可交换 对于矩阵 A A A&#xff0c;若存在两种运算 ? ? ?和 ? ? ?&#xff0c;使得 ( A ? ) ? ( A ? ) ? (A^{?})^{?}\ (A^{?})^{?} (A?)? (A?)?&#xff0c;这意味着这两种运算的顺序可以交换。由此我们得到以下三个重要等式&#xff1a; ( A …...

t113-qt

修改QT配置: # # qmake configuration for building with arm-linux-gnueabi-g ## MAKEFILE_GENERATOR UNIX # CONFIG incremental # QMAKE_INCREMENTAL_STYLE sublib# include(../common/linux.conf) # include(../common/gcc-base-unix.conf) # inc…...

SQL自学,mysql从入门到精通 --- 第 14天,主键、外键的使用

1.主键 PRIMARY KEY 主键的使用 字段值不允许重复,且不允许赋NULL值 创建主键 root@mysqldb 10:11: [d1]> CREATE TABLE t3(-> name varchar(10) PRIMARY KEY,-> age int,-> class varchar(8)-> ); Query OK, 0 rows affected (0.01 sec)root@mysqldb 10:…...

整合 Redis 分布式锁:从数据结构到缓存问题解决方案

引言 在现代分布式系统中&#xff0c;Redis 作为高性能的键值存储系统&#xff0c;广泛应用于缓存、消息队列、实时计数器等多种场景。然而&#xff0c;在高并发和分布式环境下&#xff0c;如何有效地管理和控制资源访问成为一个关键问题。Redis 分布式锁正是为了解决这一问题…...

ASP.NET Core WebSocket、SignalR

目录 WebSocket SignalR SignalR的基本使用 WebSocket WebSocket基于TCP协议&#xff0c;支持二进制通信&#xff0c;双工通信。性能和并发能力更强。WebSocket独立于HTTP协议&#xff0c;不过我们一般仍然把WebSocket服务器端部署到Web服务器上&#xff0c;因为可以借助HT…...

array_walk. array_map. array_filter

1. array_walk 函数 array_walk 用于遍历数组并对每个元素执行回调函数。它不会受到数组内部指针位置的影响&#xff0c;会遍历整个数组。回调函数接收的前两个参数分别是元素的值和键名&#xff0c;如果有第三个参数&#xff0c;则数组所有的值都共用这个参数。 示例代码&am…...

解锁国内主流前端与后端框架

前端框架大揭秘 在当今的 Web 开发领域&#xff0c;前端框架的地位愈发举足轻重。随着用户对 Web 应用交互性和体验性要求的不断攀升&#xff0c;前端开发不再仅仅是简单的页面布局与样式设计&#xff0c;更需要构建复杂且高效的用户界面。前端框架就像是一位得力助手&#xf…...

Nginx进阶篇 - nginx多进程架构详解

文章目录 1. nginx的应用特点2. nginx多进程架构2.1 nginx多进程模型2.2 master进程的作用2.3 进程控制2.4 worker进程的作用2.5 worker进程处理请求的过程2.6 nginx处理网络事件 1. nginx的应用特点 Nginx是互联网企业使用最为广泛的轻量级高性能Web服务器&#xff0c;其特点是…...

【PDF提取内容】如何批量提取PDF里面的文字内容,把内容到处表格或者批量给PDF文件改名,基于C++的实现方案和步骤

以下分别介绍基于 C 批量提取 PDF 里文字内容并导出到表格&#xff0c;以及批量给 PDF 文件改名的实现方案、步骤和应用场景。 批量提取 PDF 文字内容并导出到表格 应用场景 文档数据整理&#xff1a;在处理大量学术论文、报告等 PDF 文档时&#xff0c;需要提取其中的关键信…...

HTML之CSS定位、浮动、盒子模型

HTML之CSS定位、浮动、盒子模型 定位 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document<…...

【Java基础】为什么不支持多重继承?方法重载和方法重写之间区别、Exception 和 Error 区别?

Hi~&#xff01;这里是奋斗的明志&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f331;&#x1f331;个人主页&#xff1a;奋斗的明志 &#x1f331;&#x1f331;所属专栏&#xff1a;Java基础面经 &#x1f4da;本系列文章为个…...

使用scoop 下载速度慢怎么办

在国内使用 Scoop 下载速度慢是一个常见问题&#xff0c;主要是因为 Scoop 默认的软件源&#xff08;bucket&#xff09;和下载服务器通常位于国外。以下是一些提高下载速度的方法&#xff1a; 1. 更换 Scoop 镜像源&#xff08;Bucket 镜像&#xff09;&#xff1a; 原理&…...

使用Redis解决使用Session登录带来的共享问题

在学习项目的过程中遇到了使用Session实现登录功能所带来的共享问题&#xff0c;此问题可以使用Redis来解决&#xff0c;也即是加上一层来解决问题。 接下来介绍一些Session的相关内容并且采用Session实现登录功能&#xff08;并附上代码&#xff09;&#xff0c;进行分析其存在…...

OnlyOffice docker 运行(详细)

下载镜像 推荐使用 GitHub Action 方式下载&#xff1a; Action 地址&#xff1a;https://github.com/Shixuebin/DockerTarBuilder 教程地址&#xff1a;https://www.bilibili.com/video/BV1EZ421M7mL/ docker 镜像安装 docker load -i xxx.tar镜像运行 docker run -i -t -…...

CNN 卷积神经网络处理图片任务 | PyTorch 深度学习实战

前一篇文章&#xff0c;学习率调整策略 | PyTorch 深度学习实战 本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started CNN 卷积神经网络 CNN什么是卷积工作原理深度学习的卷积运算提取特征不同特征核的效果比较卷积核感受野共享权重池化 示例源码 …...

自动驾驶数据集三剑客:nuScenes、nuImages 与 nuPlan 的技术矩阵与生态协同

目录 1、引言 2、主要内容 2.1、定位对比&#xff1a;感知与规划的全维覆盖 2.2、数据与技术特性对比 2.3、技术协同&#xff1a;构建全栈研发生态 2.4、应用场景与评估体系 2.5、总结与展望 3、参考文献 1、引言 随着自动驾驶技术向全栈化迈进&#xff0c;Motional 团…...

02.07 TCP服务器与客户端的搭建

一.思维导图 二.使用动态协议包实现服务器与客户端 1. 协议包的结构定义 首先&#xff0c;是协议包的结构定义。在两段代码中&#xff0c;pack_t结构体都被用来表示协议包&#xff1a; typedef struct Pack {int size; // 记录整个协议包的实际大小enum Type type; …...

基于机器学习时序库pmdarima实现时序预测

目录 一、Pmdarima实现单变量序列预测1.1 核心功能与特性1.2 技术优势对比1.3 python案例1.3.1 时间序列交叉验证1.3.1.1 滚动交叉验证1.3.1.2 滑窗交叉验证 时间序列相关参考文章&#xff1a; 时间序列预测算法—ARIMA 基于VARMAX模型的多变量时序数据预测 基于机器学习时序库…...

计算机视觉的研究方向、发展历程、发展前景介绍

以下将分别从图像分类、目标检测、语义分割、图像分割&#xff08;此处应主要指实例分割&#xff09;四个方面&#xff0c;为你介绍研究生人工智能计算机视觉领域的应用方向、发展历程以及发展前景。 文章目录 1.图像分类应用方向发展历程发展前景 2.目标检测应用方向发展历程…...

NLP_[2]-认识文本预处理

文章目录 1 认识文本预处理1 文本预处理及其作用2. 文本预处理中包含的主要环节2.1 文本处理的基本方法2.2 文本张量表示方法2.3 文本语料的数据分析2.4 文本特征处理2.5数据增强方法2.6 重要说明 2 文本处理的基本方法1. 什么是分词2 什么是命名实体识别3 什么是词性标注 1 认…...

单硬盘槽笔记本更换硬盘

背景 本人的笔记本电脑只有一个硬盘槽&#xff0c;而且没有M.2的硬盘盒&#xff0c;只有一个移动硬盘 旧硬盘&#xff1a;512G 新硬盘&#xff1a;1T 移动硬盘&#xff1a;512G 参考链接&#xff1a;https://www.bilibili.com/video/BV1iP41187SW/?spm_id_from333.1007.t…...

在stm32mp257的yocto中设置用户名和密码

在STM32MP257的Yocto环境中设置用户名和密码,通常需要修改根文件系统的用户配置。以下是详细步骤: 1. 设置root密码 默认情况下,root账户可能无密码或使用默认密码。通过以下方法修改: 方法1:在local.conf中直接设置 # 打开Yocto工程的配置文件 vi conf/local.conf# 添…...

力扣--链表

相交链表 法一&#xff1a; 把A链表的节点都存HashSet里&#xff0c;遍历B链表找相同的节点 法二&#xff1a; 把A、B指针都移到末尾&#xff0c;再同时往回走&#xff0c;每次往回走都比较 当前节点的下一节点&#xff08;a.next b.next ?)是否相同&#xff0c;当不相同…...

【redis】数据类型之hash

Redis中的Hash数据类型是一种用于存储键值对集合的数据结构。与Redis的String类型不同&#xff0c;Hash类型允许你将多个字段&#xff08;field&#xff09;和值&#xff08;value&#xff09;存储在一个单独的key下&#xff0c;从而避免了将多个相关数据存储为多个独立的key。…...

多路文件IO

一、思维导图...

计算机网络面经

文章目录 基础HTTPHTTP报文结构 (注意)RPC和http的区别TCPTCP报文结构(注意)IP基础 HTTP HTTP报文结构 (注意) 请求行:请求方法get/post,url,http版本 请求头:用户标识,请求体长度,类型,cookie 请求体:内容 状态行:状态码,状态消息、(http版本) 响应头:内…...

非递减子序列(力扣491)

这道题的难点依旧是去重&#xff0c;但是与之前做过的子集类问题的区别就是&#xff0c;这里是求子序列&#xff0c;意味着我们不能先给数组中的元素排序。因为子序列中的元素的相对位置跟原数组中的相对位置是一样的&#xff0c;如果我们改变数组中元素的顺序&#xff0c;子序…...

00_Machine Vision_基础介绍

基础概念 由于计算机只能处理离散的数据&#xff0c;所以需要将连续的图片转化为离散的数据。主要包含&#xff1a;空间离散以及灰度值离散 空间离散&#xff1a;将图片的像素点离散化&#xff0c;即将图片的像素点转化为一个个的小方块&#xff0c;即为图片的分辨率。分辨率…...

排错 -- 用React.js,Solidity,智能合约构建最新区块链应用

真枪实弹:第一个Web3项目【上集】用React.js,Solidity,智能合约构建最新区块链应用详细教程 构建web跟随b站教程中遇到了很多错误&#xff0c;从今天开始构建完整的应用&#xff0c;在此记录一些排错。 问题情况1&#xff1a;跟随视频后无Src文件 问题情况1解决方法&#xff1…...

【WB 深度学习实验管理】利用 Hugging Face 实现高效的自然语言处理实验跟踪与可视化

本文使用到的 Jupyter Notebook 可在GitHub仓库002文件夹找到&#xff0c;别忘了给仓库点个小心心~~~ https://github.com/LFF8888/FF-Studio-Resources 在自然语言处理领域&#xff0c;使用Hugging Face的Transformers库进行模型训练已经成为主流。然而&#xff0c;随着模型复…...

ximalaya(三) playUriList值解密--webpack

本文主要介绍解密音频播放url参数。 本文仅代表个人理解&#xff0c;如有其他建议可在评论区沟通。 声明 仅仅记录一下自己的学习方法&#xff0c;不作为其他参考、更不作为商业用途。如有侵犯请联系本人删除 目标地址&#xff1a;aHR0cHM6Ly93d3cueGltYWxheWEuY29tL3NvdW5k…...

ES6 Map 数据结构是用总结

1. Map 基本概念 Map 是 ES6 提供的新的数据结构&#xff0c;它类似于对象&#xff0c;但是"键"的范围不限于字符串&#xff0c;各种类型的值&#xff08;包括对象&#xff09;都可以当作键。Map 也可以跟踪键值对的原始插入顺序。 1.1 基本用法 // 创建一个空Map…...

使用Redis实现业务信息缓存(缓存详解,缓存更新策略,缓存三大问题)-更新中

一、什么是缓存&#xff1f; 缓存是一种高效的数据存储方式&#xff0c;它通过将数据保存在内存中来提供快速的读写访问。这种机制特别适用于需要高速数据访问的应用场景&#xff0c;如网站、应用程序和服务。在处理大量数据和高并发请求时&#xff0c; 缓存能显著提高性能和用…...

Windows 系统下使用 Ollama 离线部署 DeepSeek - R1 模型指南

引言 随着人工智能技术的飞速发展&#xff0c;各类大语言模型层出不穷。DeepSeek - R1 凭借其出色的语言理解和生成能力&#xff0c;受到了广泛关注。而 Ollama 作为一款便捷的模型管理和部署工具&#xff0c;能够帮助我们轻松地在本地环境中部署和使用模型。本文将详细介绍如…...

1.2 变革里程碑:Transformer 的崛起

变革里程碑&#xff1a;Transformer 的崛起 一、架构革命的核心驱动力 #mermaid-svg-hsXnwHI0wO2qZaqb {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#000000;}#mermaid-svg-hsXnwHI0wO2qZaqb .error-icon{fill:#552222;}#mermaid-sv…...

SpringBoot速成(八)登录实战:未登录不能访问 P5-P8

1.登录 package com.itheima.springbootconfigfile.controller;import com.itheima.springbootconfigfile.pojo.Result; import com.itheima.springbootconfigfile.pojo.User; import com.itheima.springbootconfigfile.service.UserService;import com.itheima.springbootco…...

[Unity角色控制专题] 详细说明如何使用Character Controller配合脚本实现类似MC的第一人称控制(仅移动与视角摇晃)

关于角色控制器的基本用法我就不做介绍了&#xff0c;请自行查看相关文档&#xff1a; Unity - Manual: Character Controller component reference 本文用到了三角函数和插值函数&#xff0c;非常简单&#xff0c;如有疑问请查询以下文章: Unity中的数学 之 Mathf_uni…...

2025_2_9 C语言中队列

1.队列&#xff08;先进先出&#xff09; 队列也是一种受限制的线性结构 它只能在一端添加元素&#xff0c;在另一端访问&#xff0c;删除元素 &#xff08;队首插入&#xff0c;队尾删除&#xff09; 因为链表实现没有数组实现快&#xff0c;所以队列大多数是用数组实现的 q…...

(原创,可用)SSH实现内外网安全穿透(安全不怕防火墙)

目前有A、B终端和一台服务器&#xff0c;A、B机器不能直接访问&#xff0c;服务器不能直接访问A、B终端但是A、B终端可以访问服务器&#xff0c;这个场景很像我们有一台电脑在单位内网&#xff0c;外机器想访问内网系统&#xff0c;可能大家目前想到的就是frp之类穿透工具&…...

mysql安装starting the server报错

win10家庭版无法启动服务的&#xff0c;先不要退出&#xff0c;返回上一栏&#xff0c;然后通过电脑搜索栏输入服务两个字&#xff0c;在里面找到mysql80&#xff0c;右键属性-登录&#xff0c;登录身份切换为本地系统就行了...

设计高效的测试用例:从需求到验证

在现代软件开发过程中&#xff0c;测试用例的设计一直是质量保证&#xff08;QA&#xff09;环节的核心。有效的测试用例不仅能够帮助发现潜在缺陷&#xff0c;提升软件质量&#xff0c;还能降低后期修复成本&#xff0c;提高开发效率。尽管如此&#xff0c;如何从需求出发&…...

【阅读笔记】信息熵自动曝光An Automatic Exposure Algorithm Based on Information Entropy

一、算法背景 信息熵作为衡量图像信息量的重要指标&#xff0c;能够反映图像的细节丰富程度。通过基于信息熵的自动曝光算法&#xff0c;可以自动调整曝光时间&#xff0c;使图像包含更多信息&#xff0c;从而提高图像质量。 灰度直方图在各个灰度值上分布越均匀&#xff0c;…...