计算机网络—HTTP协议:深入解析与应用实践

news2025/2/25 6:10:22

                                        🎬慕斯主页修仙—别有洞天

                                       ♈️今日夜电波:ヒステリックナイトガール

                                                           1:03━━━━━━️💟──────── 5:06
                                                                🔄   ◀️   ⏸   ▶️    ☰  

                                 💗关注👍点赞🙌收藏您的每一次鼓励都是对我莫大的支持😍


 

目录

什么是HTTP协议?

URL

什么是URL?

urlencode和urldecode

HTTP请求和响应的格式

HTTP请求格式

HTTP的方法

HTTP响应格式

HTTP的状态码

HTTP常见Header

请求头(Request Header)

响应头(Request Header)

设计一个简单的HTTP服务器

解析HTTP请求格式

根据上面解析出来的数据创建服务器

一些细节的知识

重定向

Cookie


什么是HTTP协议?

        HTTP协议,全称Hypertext Transfer Protocol,即超文本传输协议,是互联网上应用最为广泛的一种网络传输协议。它定义了客户端(如浏览器)与服务器之间的通信规范,以实现对各种资源(如HTML页面、图像、音频、视频等)的传输和访问。HTTP协议基于请求响应模式,客户端向服务器发送请求消息,请求消息中包含请求方法、URL、协议版本以及请求头等信息。服务器接收到请求消息后,根据请求消息的URL和相应的处理逻辑,生成服务器响应消息,并将其发送给客户端。响应消息中包含协议版本、状态码、响应头和响应体等信息。客户端接收到响应消息之后,会根据自身的处理方式进行处理,例如如果是网页,客户端会解析响应体中的HTML代码并渲染出网页。

URL

什么是URL?

        平时我们俗称的 "网址" 其实就是说的 URL,如下图所示:

        需要注意的是:http默认绑定的端口号是80、https默认绑定的端口号是443。而其中的服务器地址实际上就是我们的ip地址,如下的地址是相同的:我们可以指定端口来访问。如果不指定则会使用默认的端口。

http://www.qq.com:80      ==        61.241.54.232:80

        实际上我们看到服务器网址后带的文件路径我们这个时候就很清楚了,这不就是我们在Linux中常用的文件目录结构吗?实际上也的确是这样的,我们通过URL请求服务,可以带上指定的路径,将该路径下的资源文件返回给用户。

        对于带层次的文件路径来说,第一个 / 表示为web根目录,第二个 / 开始表示为路径分隔符。 // 通常被当作单个斜杠来处理。

        ?表示为查询字符串的开头,参数和数值使用键值对的形式(KV结构)进行表示,多个键值对之间使用与号(&)分隔。例如,?param1=value1&param2=value2。

        # 表示为片段标识的开头,后面跟着资源的特定部分或ID。它主要用于客户端的导航,不会被发送到服务器。

urlencode和urldecode

        像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现.比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.

        转义的规则如下:将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。如下:

HTTP请求和响应的格式

        下面是对上述图解的解释:

        HTTP请求和响应的格式在Web开发中非常重要,它们定义了客户端(通常是浏览器)和服务器之间如何通信。以下是关于HTTP请求和响应格式的简要概述:(需要注意的是:他们通常使用\r\n进行分隔)

HTTP请求格式

        HTTP请求通常由以下部分组成:

  1. 请求行(Request Line):包含HTTP方法(如GET、POST等)、请求的URL和HTTP版本(如HTTP/1.1)。
GET /example.html HTTP/1.1

  1. 请求头部(Request Headers):包含关于请求的各种元数据,如浏览器类型、请求来源、内容类型等。
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
...
  1. 空行:请求头部之后是一个空行,用于分隔请求头部和请求体。
  2. 请求体(Request Body):对于某些HTTP方法(如POST或PUT),请求体包含发送到服务器的数据。这通常用于提交表单或上传文件。

        下面对于其中的细节进行详细的叙述:

HTTP的方法

        我们比较常用的就是GET和POST方法,下面详细介绍:

        GET方法主要用于请求获取指定的资源。当客户端(如Web浏览器)使用GET方法向服务器发起请求时,它会将请求的参数附加到URL的末尾,并以明文形式发送。这些参数通常是以键值对的形式存在,并且在URL中可见。由于GET请求的参数直接暴露在URL中,因此它不适合处理敏感数据,如密码或金额等。此外,GET请求只产生一个TCP数据包,且浏览器会缓存GET请求的结果,这意味着如果用户回退或刷新页面,浏览器不会再次发送请求,而是从缓存中获取结果。GET请求还具有幂等性,即多次执行相同的GET请求,服务器返回的结果都是一样的。

        与GET方法不同,POST方法主要用于向指定资源提交数据进行处理,如提交表单或上传文件。当使用POST方法时,提交的数据会放置在HTTP请求的主体中,而不是附加到URL上。这意味着POST请求可以提交大量的数据,且数据在传输过程中不会明文显示,从而提高了安全性。然而,由于POST请求不会缓存,每次用户回退或刷新页面时,浏览器都需要重新发送请求。此外,POST请求是非幂等的,即多次执行相同的POST请求可能会导致不同的结果。

HTTP响应格式

HTTP响应同样由几个部分组成:

  1. 状态行(Status Line):包含HTTP版本、状态码和状态消息。状态码用于表示请求的处理结果,如200表示成功,404表示未找到资源等。
HTTP/1.1 200 OK

  1. 响应头部(Response Headers):包含关于响应的各种元数据,如内容类型、内容长度、服务器类型等。
Content-Type: text/html; charset=UTF-8
Content-Length: 12345
Server: Apache/2.4.46 (Unix)
...

  1. 空行:响应头部之后同样是一个空行,用于分隔响应头部和响应体。
  2. 响应体(Response Body):这是服务器返回给客户端的实际数据,可以是HTML、JSON、XML等任何格式。

        请注意,不是所有的HTTP请求都包含请求体(例如GET请求),同样也不是所有的HTTP响应都包含响应体(例如某些只包含状态信息的响应)。

        下面对于其中的细节进行详细的叙述:

HTTP的状态码

        常见的状态码:

200 OK:表示请求已成功处理,并返回了所请求的资源。这是最常见的成功状态码。

302Redirect表示临时重定向。当服务器返回302状态码时,意味着请求的资源已被临时移动到另一个位置,并且服务器会提供一个新的URL地址,以便客户端能够重新发送请求并获取所需资源。

403 Forbidden:表示服务器拒绝了客户端的请求,因为客户端没有访问权限。这可能是因为客户端未经授权或身份验证失败,或者服务器设置了访问限制。

404 Not Found:表示请求的资源在服务器上不存在。当客户端发起请求时,如果服务器无法找到与请求URL对应的资源,通常会返回这个状态码。

500 Internal Server Error:表示服务器在处理请求时遇到了内部错误。这可能是由于服务器上的代码或配置错误导致的。

504 Bad Gateway :表示网关超时(Gateway Timeout),它是一种服务器端错误响应状态码。当客户端(如浏览器)向服务器发送请求时,如果服务器在一定时间内无法从上游服务器(例如应用程序服务器、数据库服务器)获取到响应,就会返回504错误码给客户端。

HTTP常见Header

请求头(Request Header)
  1. Host:指定目标服务器的主机名或IP地址。
  2. Accept:定义客户端能够接受来自服务器的媒体类型,如application/json, text/html等。这允许服务器发送满足客户端需求的资源。
  3. User-Agent:标识发出请求的Web浏览器或客户端应用程序,使服务器能够根据客户端定制其响应。
  4. Content-Type:标识请求主体中内容的媒体类型,帮助服务器成功解释和处理有效负载。
  5. Cache-Control:指定请求或响应的缓存策略,如max-age、no-cache、no-store等。
  6. 自定义请求头
    • X-Forwarded-Host:在HTTP代理或负载均衡器后面使用。
    • X-Forwarded-For:用于记录客户端的IP地址,特别在使用代理服务器时。
    • X-Requested-With:用于指示请求的类型,如XMLHttpRequest。
    • X-Csrf-Token:用于防止跨站请求伪造攻击。
    • X-Content-Type-Options:用于指示浏览器是否应该自动处理响应体的MIME类型,如nosniff。
    • X-XSS-Protection:用于启用浏览器内置的跨站脚本攻击防护机制。

响应头(Request Header)
  1. Content-Type:这个字段指明了响应主体的媒体类型,即客户端可以如何解析响应的内容。例如,对于HTML页面,该字段的值通常是text/html;对于JSON数据,值则是application/json。
  2. Content-Length:这个字段表示响应主体的长度,以字节为单位。这有助于客户端正确读取整个响应内容。
  3. Date:这个字段表示响应生成的日期和时间,格式为RFC 7231规定的日期时间格式。
  4. Cache-Control:这个字段用于指定缓存策略,控制响应内容在客户端和中间缓存中的缓存行为。例如,no-cache表示每次都需要向服务器验证缓存的内容是否仍然有效;max-age则指定了缓存内容的有效期。
  5. Expires:这个字段用于指定缓存内容的过期时间。与Cache-Control的max-age相比,Expires使用了一个绝对的时间戳来表示过期时间。
  6. ETag:这个字段用于标识响应内容的一个版本,如果内容未发生变化,服务器可以在后续的请求中通过比较ETag来避免发送相同的内容。
  7. Last-Modified:这个字段表示资源最后一次被修改的日期和时间,有助于客户端判断是否需要重新获取资源。
  8. Set-Cookie:这个字段用于设置HTTP cookie,用于会话管理、用户身份验证等目的。
  9. Location搭配3XX状态码使用,指定重定向的目标URL。
  10. Server:这个字段包含了处理请求的服务器软件的名称和版本。
  11. Connection:这个字段用于控制网络连接的行为,例如是否保持连接(keep-alive)或关闭连接。
  12. WWW-Authenticate:当服务器需要客户端提供身份验证信息时,这个字段会被包含在401 Unauthorized响应中,以指示客户端如何进行身份验证。

        下面我们以浏览器作为客户端,向我们自行编写的一个小程序进行访问,看看是否如我们所叙述的一样:

        该程序仅仅是将报文给打印出来,并没有做什么特殊的处理,可以看到正如我们上面所说的,结构层次是相同的,由于没有带正文所以在空行后的正文内容是空的。

        那如果我们想要给客户端返回信息呢?当然也是同上面所叙述的一样,以响应的格式按照HTTP协议的要求给他返回对应的报文,如下,我们按照规则返回一个简单的字符串“hello world!”

             //返回响应过程
            std::string text="Hello world!";
            std::string response_line="HTTP/1.0 200 OK\r\n";
            std::string response_header="Content-Length: ";
            response_header+=std::to_string(text.size());
            response_header+="\r\n";
            std::string blank_line="\r\n";

            std::string response=response_line;
            response+=response_header;
            response+=blank_line;
            response+=text;
            send(sockfd,response.c_str(),response.size(),0);

        效果如下:

        需要特别注意的是:网页必须指明编码格式,也就是Content-Type。否则就会出现乱码。通常根据文件的后缀来区别。比如:如果我们放回的是html格式则按照Content-Type对照表返回text/html,png则是image/png。

设计一个简单的HTTP服务器

解析HTTP请求格式

        按照要求我们创建一个Deserialize函数用于解析和处理通过HTTP发送过来的报文,最主要的就是sep=\r\n这个分隔符,根据他我们可以将请求行到Header全部解析,最后根据空行我们可以得到后面的请求正文。创建一个Parse函数用于解析请求方法、URL、http_version,最后分析URL,获得文件路径、要打开的文件类型。

class HttpRequest
{
public:
    void Deserialize(std::string req)
    {
        while (true)
        {
            std::size_t pos = req.find(sep);
            if (pos == std::string::npos)
                break;
            std::string tmp = req.substr(0, pos);
            if (tmp.empty())
                break;
            req_header.push_back(tmp);
            req.erase(0, pos + sep.size());
        }
        text = req;
    }

    void Parse()
    {
        std::stringstream ss(req_header[0]);
        ss >> method >> url >> http_version;
        file_path = wwwroot;
        if (url == "/" || url == "/index.html")
        {
            file_path += "/";
            file_path += homepage; //./wwwroot/index.html
        }
        else
        {
            file_path += url;
        }

        auto pos = file_path.rfind(".");
        if (pos == std::string::npos)
            suffix = ".html";
        else
            suffix = file_path.substr(pos);
    }

public:
    std::vector<std::string> req_header;
    std::string text;

    // 解析之后的结果
    std::string method;
    std::string url;
    std::string http_version;
    std::string file_path; // ./wwwroot/a/b/c.html 2.png

    std::string suffix;
};

根据上面解析出来的数据创建服务器

        这里我们复用了之前实现的socket和日志接口,在初始化的时候仅仅需要传入端口即可,同时我们先自定义仅有两种类型的文件“html”和“png”。这两个分别是给Header中的Content-Type 用的。

        这个服务器使用简易的多线程来实现多人链接,调用pthread_create的函数ThreadRun会使用pthread_deatch来让线程无需等待。一些线程的细节不多叙述啦~

        最主要的还是其中对于http协议的处理函数HandlerHttp。他会读取建立了tcp链接的http协议发来的报文,接着按照报文进行解析,按照我们制定的要求返回响应过程。具体的响应报文下面仅仅给出一些例子:

class HttpServer

class ThreadData
{
public:
    ThreadData(int soc, HttpServer *s)
        : sockfd(soc), svr(s)
    {
    }

public:
    int sockfd;
    HttpServer *svr;
};

class HttpServer
{
public:
    HttpServer(uint16_t port = defaultport) : port_(port)
    {
        content_type.insert({".html", "text/html"});
        content_type.insert({".png", "image/png"});
    }
    bool Start()
    {
        listensock_.Socket();
        listensock_.Bind(port_);
        listensock_.Listen();
        for (;;)
        {
            std::string clientip;
            uint16_t clientport;
            int sockfd = listensock_.Accept(&clientip, &clientport);
            lg(Info, "get a new connect, sockfd: %d", sockfd);
            pthread_t tid;
            ThreadData *td = new ThreadData(sockfd, this);

            pthread_create(&tid, nullptr, ThreadRun, td);
        }
    }

    static std::string ReadHtmlContent(const std::string &hemlpath)
    {
        std::ifstream in(hemlpath, std::ios::binary);
        if (!in.is_open())
            return "";
        //获得文件总大小
        in.seekg(0, std::ios_base::end);
        auto len = in.tellg();
        //回到开头
        in.seekg(0, std::ios_base::beg);
        std::string content;
        content.resize(len);

        in.read((char*)content.c_str(), content.size());

        in.close();

        return content;
    }

    std::string SuffixToDesc(const std::string &suffix)
    {
        auto iter = content_type.find(suffix);
        if(iter == content_type.end()) return content_type[".html"];
        else return content_type[suffix];
    }

    void HandlerHttp(int sockfd)
    {
        char buffer[10240];
        ssize_t n = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
        if (n > 0)
        {
            buffer[n] = 0;
            std::cout << buffer;
            HttpRequest req;
            req.Deserialize(buffer);
            req.Parse();
            // 返回响应过程
            std::string text;
            bool ok = true;
            text = ReadHtmlContent(req.file_path);
            if(text.empty())
            {
                ok = false;
                std::string err_html = wwwroot;
                err_html += "/";
                err_html += "err.html";
                text = ReadHtmlContent(err_html);
            }
            std::string response_line;
            if(ok)
            response_line = "HTTP/1.0 200 OK\r\n";
            else
            response_line = "HTTP/1.0 404 Not Found\r\n";

            std::string response_header = "Content-Length: ";
            response_header += std::to_string(text.size());
            response_header += "\r\n";

            response_header += "Content-Type: ";
            response_header += SuffixToDesc(req.suffix);
            response_header += "\r\n";
            std::string blank_line = "\r\n";

            std::string response = response_line;
            response += response_header;
            response += blank_line;
            response += text;
            send(sockfd, response.c_str(), response.size(), 0);
        }
        close(sockfd);
    }

    static void *ThreadRun(void *args)
    {
        pthread_detach(pthread_self());
        ThreadData *td = static_cast<ThreadData *>(args);
        td->svr->HandlerHttp(td->sockfd);

        delete td;
        return nullptr;
    }

private:
    Sock listensock_;
    uint16_t port_;
    std::unordered_map<std::string, std::string> content_type;
};

        结合HTML我们可以实现如下的效果:

        借用了一位大佬的HTML代码:

        当遇到访问错误的路径时可以合理的处理:

 

一些细节的知识

        在了解完上面的知识后,相信对于http已经有了一定的认识。下面讲讲细节的东西:

重定向

        前面提到有3开头的状态码,这是重定向状态码。这里要详细介绍一下永久重定向和临时重定向的区别:

        永久重定向(HTTP状态码301)表示原URL不应再被使用,而新的URL应替换它。这通常发生在站点更改其URL结构后,以确保旧的链接或书签能够继续有效。这种重定向是永久性的,一旦实施,搜索引擎和其他客户端应更新其索引和缓存,以反映新的URL。

        临时重定向(HTTP状态码302)则意味着请求的资源已被临时移动到其他位置,并且服务器已经提供了新的URL,以便客户端可以重新发送请求。这种重定向是暂时的,可能由于资源暂时不可用或正在进行维护等原因而发生。当资源恢复其原始位置或维护完成后,客户端应继续使用原始URL。

        在搜索引擎优化的角度,永久重定向对于确保网站的排名和流量至关重要,因为它告诉搜索引擎旧的URL已被新的URL永久替代。而临时重定向则不会对搜索引擎的排名产生长期影响,因为搜索引擎知道这只是暂时的变化。

        需要注意的是:上述的重定向都是会搭配header中介绍过的Location搭配3XX状态码使用,指定重定向的目标URL)使用。

        我们要重定向则可以在响应行和header中添加对应的状态码和header和kv结构即可。如下:

            std::string response_line="HTTP/1.0 301 Moved Permanently\r\n";//永久重定向
            //std::string response_line="HTTP/1.0 302 Found\r\n";//临时重定向
            std::string response_header = "Location: http://www.qq.com";
            response_header += "\r\n";

Cookie

        Cookie 是一种在 Web 开发中广泛使用的技术,用于在客户端(通常是用户的浏览器)存储信息。这些信息可以是用户偏好、会话状态或其他任何需要在多次请求和页面加载之间保持的数据。

        以下是关于 Cookie 的详细解释:

1. 基本概念

  • 定义:Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器后续向同一服务器发送请求时被携带上,用于实现用户跟踪和会话管理等功能。
  • 作用:通过 Cookie,服务器可以识别特定的用户,并根据之前保存的信息为用户提供个性化的内容或服务。

2. 工作原理

  1. 设置 Cookie:当服务器响应一个 HTTP 请求时,它可以通过在 HTTP 响应头中设置 Set-Cookie 字段来发送一个或多个 Cookie 到客户端。这样客户端就可以使用这些数据,一些操作如:验证身份操作就不用重复的进行了。
  2. 接收和存储 Cookie:浏览器在接收到含有 Set-Cookie 的响应后,会将这些 Cookie 存储在本地。
  3. 发送 Cookie:在后续的 HTTP 请求中,浏览器会自动将之前存储的 Cookie 通过 Cookie 请求头发送到服务器。

3.Cookie的分类

  1. 内存Cookie:也被称为非持久Cookie或会话Cookie。这种Cookie是由浏览器维护并保存在内存中的,因此其存在时间是短暂的。当电脑关机或浏览器关闭后,内存Cookie就会自动消失。
  2. 硬盘Cookie:也被称为持久Cookie。这种Cookie保存在硬盘中,一般是在浏览器的目录下有一个文件单独存放。硬盘Cookie有一个过期时间,除非用户手动删除或者cookie过期,否则cookie不会被删除,其存在时间是长期的。

        如下便是一个网站的例子:

        大致的代码理解:

            std::string response_line="HTTP/1.0 200 OK\r\n";
            response_header += "Set-Cookie: name=XIXI";
            response_header += "\r\n";
            response_header += "Set-Cookie: password=12345678";
            response_header += "\r\n";

4、Cookie安全问题

        Cookie的安全性是一个重要的议题,因为它们包含了用户的个人信息和会话状态,如果这些信息被恶意利用,可能会导致隐私泄露、身份冒用等安全问题。

5、Session ID

        Session ID是编程中用于跟踪和管理用户会话的重要概念。在Web开发中,会话是指用户与应用程序之间的交互过程,它可以跨越多个页面请求,使应用程序能够在多个页面之间保持状态。例如,当用户登录到网站时,会话可以用来跟踪用户的身份验证状态,以便在用户浏览其他页面时保持其登录状态。

        为了实现会话跟踪,Web应用程序通常会为每个用户分配一个唯一的会话标识符,即Session ID。这个标识符由应用服务器在用户连接时生成,并用于在服务器端存储与特定用户相关的会话信息。Session ID通常可以保存在客户端的Cookie中,或者在URL中作为参数传递。当客户端提交页面请求时,会将这个Session ID发送回服务器,服务器通过解析这个ID来查找和读取对应的会话数据。

        之后访问时,Http 请求都会携带Session id,就可以通过Session id判断是否合法,若合法则可以访问这个资源。虽然仍然可以被窃取,但是一些私人信息还是可以得到保证的。比如:账号密码就不用当心泄露了。

        Session ID的生成过程通常发生在浏览器第一次请求服务器时,服务器会生成一个Session ID并返回给浏览器,这个ID会被保存在浏览器的会话Cookie中。Session在服务器上的默认有效时间通常是30分钟,但可以通过编程设置进行更改。

        然而,值得注意的是,由于Session ID存储在客户端的Cookie中,因此一旦客户端禁用了Cookie,Session也会失效。因此,在使用Session ID进行会话管理时,需要考虑到Cookie可能不可用的情况,并采取适当的备选方案来维护用户的会话状态。

 


                        感谢你耐心的看到这里ღ( ´・ᴗ・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o! 

                                       

                                                                        给个三连再走嘛~  

 

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

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

相关文章

This app has no Android key hashes configured. . Configure your app key

Unity 接入 Facebook SDK 的过程中遇到这个问题&#xff0c;查了很多帖子&#xff0c;不太直观&#xff0c;记录下来方便需要的同学参考 报上面错误的原因是在https://developers.facebook.com/apps/ 设置里没有填入有效的密钥 怎么填入这个密钥呢&#xff0c;其实很简单&…

微电网优化:基于巨型犰狳优化算法(Giant Armadillo Optimization,GAO)的微电网优化(提供MATLAB代码)

一、微电网优化模型 微电网是一个相对独立的本地化电力单元&#xff0c;用户现场的分布式发电可以支持用电需求。为此&#xff0c;您的微电网将接入、监控、预测和控制您本地的分布式能源系统&#xff0c;同时强化供电系统的弹性&#xff0c;保障您的用电更经济。您可以在连接…

蓝桥杯 - 穿越雷区

解题思路&#xff1a; dfs 方法一&#xff1a; import java.util.Scanner;public class Main {static char[][] a;static int[][] visited;static int[] dx { 0, 1, 0, -1 };static int[] dy { 1, 0, -1, 0 };static long min Long.MAX_VALUE;static long count 0;publi…

HuggingFace踩坑记录-连不上,根本连不上

学习 transformers 的第一步&#xff0c;往往是几句简单的代码 from transformers import pipelineclassifier pipeline("sentiment-analysis") classifier("We are very happy to show you the &#x1f917; Transformers library.") ""&quo…

DSP实时计算平台设计方案:912-基于6U CPCIe的双路光纤图像DSP实时计算平台

基于6U CPCIe的双路光纤图像DSP实时计算平台 一、设备概述 设备基于6U CPCIe架构&#xff0c;通过背板交换实现4片信号处理板卡的互联传输&#xff0c;每个信号处理板卡支持双TMS320C6678&#xff0c;支持2路光纤的图像处理&#xff0c;实现FPGA的预处理和备份工…

11 - 三八译码器和存储器组织

---- 整理自B站UP主 踌躇月光 的视频 1. 38译码器 1.1 真值表 A2A1A0O7O6O5O4O3O2O1O00000000000100100000010010000001000110000100010000010000101001000001100100000011110000000 O 0 A 2 ‾ A 1 ‾ A 0 ‾ O 1 A 2 ‾ A 1 ‾ A 0 O 2 A 2 ‾ A 1 A 0 ‾ O 3 A 2 ‾ A…

c语言--枚举类型(声明、使用、优点)

目录 一、枚举类型的声明二、 枚举类型的优点三、 枚举类型的使用 一、枚举类型的声明 枚举顾名思义就是一一列举。 把可能的取值⼀⼀列举。 比如我们现实生活中&#xff1a; ⼀周的星期⼀到星期日是有限的7天&#xff0c;可以⼀⼀列举 性别有&#xff1a;男、女、保密&#x…

vscode 连接远程服务器 服务器无法上网 离线配置 .vscode-server

离线配置 vscode 连接远程服务器 .vscode-server 1. .vscode-server下载 使用vscode连接远程服务器时会自动下载配置.vscode-server文件夹&#xff0c;如果远程服务器无法联网&#xff0c;则需要手动下载 1&#xff09;网址&#xff1a;https://update.code.visualstudio.com…

【蓝桥杯-单链表-网络寻路】

蓝桥杯-单链表-网络寻路 单链表基本操作操作一&#xff1a;向链表头插入一个数操作二:在第 k个插入的数后插入一个数操作三&#xff1a;删除第 k个插入的数后面的一个数&#xff1b; P8605 [蓝桥杯 2013 国 AC] 网络寻路 单链表基本操作 初始化有关操作 // head 表示头结点的…

Spring Boot 接入 Redis

Spring Boot 接入 Redis 简介 Redis 是一种访问速度非常快的内存数据结构存储&#xff0c;用作数据库、缓存、消息代理和流引擎。提供 strings、hashes、lists、sets 等数据结构。可以解决会话缓存、消息队列、分布式锁、定期将数据集存储到硬盘等功能。 通过 Redis 设计实现…

瑞吉外卖实战学习--15、批量启售和批量禁售

批量启售和批量禁售 前言代码实现 前言 代码实现 通过url我们可以获取到传过来的ids和状态值&#xff0c;现根据状态值查询出来相关数据然后直接附加状态值最后通过updateBatchById来进行修改 PostMapping("/status/{status}")public R<String> updateStatus(…

电子台账:用控件颜色提高工作效率和数据质量

目录 1 前言 2 用页签颜色表示月度数据锁定状态 3 模板制作中定位数据源表格及其行列 3.1 鼠标移过水平过滤模板 3.2 鼠标移过垂直过滤模板 4 数据抓取过程对账页和源单元格同时染色 5 数据溯源过程&#xff0c;对企业数据源单元格染色 6 用键盘进行数据编辑后 1 前言 …

【c++】初阶模版与STL简单介绍

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;本篇文章介绍一下模版和对STL进行简单的介绍&#xff0c;后续我们进入对STL的学习&#xff01; 目录 模版1.泛型编程2.函数模板2.1函数模板的原理2.2模版的实例化…

(学习日记)2024.04.08:UCOSIII第三十六节:事件

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

【JavaSE】接口 详解(上)

前言 本篇会讲到Java中接口内容&#xff0c;概念和注意点可能比较多&#xff0c;需要耐心多看几遍&#xff0c;我尽可能的使用经典的例子帮助大家理解~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 接口 语法…

YoloV8改进策略:BiFPN+小目标分支实现小目标检测精度的大幅度上升

摘要 这几天有粉丝提到了BiFPN解决小目标问题&#xff0c;我结合我的经验&#xff0c;将BiFPN和小目标分支结合实现小目标任务检测精度的上升。 BiFPN 论文&#xff1a;https://arxiv.org/pdf/1911.09070v2.pdf BiFPN&#xff0c;全称Bi-directional Feature Pyramid Netwo…

leetcode.24. 两两交换链表中的节点

题目 给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。 你不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 思路 创建虚拟头节点&#xff0c;画图&#xff0c;确认步骤。 实现 /*** Definition for singly-li…

阿德勒、荣格、埃里克森、霍妮、弗洛姆、沙利文的新精神分析理论

新精神分析理论&#xff0c;强调自我的自主性及其整合与调节功能&#xff0c;强调文化和社会因素对人格的重大影响。 一、阿德勒的个体心理学 阿德勒&#xff0c;是一个男人努力克服自卑感的优秀样板。阿德勒写了《超越与自卑》。 阿德勒&#xff0c;向意识层面扩展精神分析…

SpringBoot快速入门笔记(4)

文章目录 一、Vue框架1、前端环境准备2、简介3、快速开始4、事件绑定 二、Vue组件化开发1、NPM2、Vue Cli3、组件化开发4、SayHello自定义组件5、Movie自定义组件 一、Vue框架 1、前端环境准备 编码工具&#xff1a;VSCode 依赖管理&#xff1a;NPM 项目构建&#xff1a;VueCl…

【Mathematical Model】基于Python实现随机森林回归算法特征重要性评估线性拟合

前段时间在做遥感的定量反演&#xff0c;所以研究了一下回归算法&#xff0c;由于之前发的几篇博文都是定义好基础方程进行拟合的&#xff0c;不太满足我的需求。所以研究了一下随机森林回归的算法&#xff0c;之前使用随机森林都是做分类&#xff0c;这次做了回归算法也算是补…