【网络】3.HTTP(讲解HTTP协议和写HTTP服务)

目录

  • 1 认识URL
    • 1.1 URI的格式
  • 2 HTTP协议
    • 2.1 请求报文
    • 2.2 响应报文
  • 3 模拟HTTP
    • 3.1 Socket.hpp
    • 3.2 HttpServer.hpp
      • 3.2.1 start()
      • 3.2.2 ThreadRun()
      • 3.2.3 HandlerHttp()
  • 总结

1 认识URL

什么是URI?

URI 是 Uniform Resource Identifier的缩写,URI就是由某个协议方案表示的资源的定位标识符。采用HTTP协议时,协议方案就是http。除此之外,还有ftp、mailto、telnet等。

什么是URL?

URI用字符串标识某一互联网资源,而URL表示资源的地点(互联网上所处的位置)。可见URL是URI的子集。

1.1 URI的格式

在这里插入图片描述
登录信息认证

指定用户名和密码作为从五毒气短获取资源时必要的登录信息(身份认证)。此项是可选项。

服务器地址

使用绝对URI必须指定带访问的服务器地址。地址可以是DNS,或者是IPV4,IPV6格式。

服务器端口号

指定服务器连接的网络端口号,如果用户省略则自动使用默认端口号。

带层次的文件路径

指定服务器上的文件路径来定位特指的资源。这与UNIX系统的文件目录结构类似。如果不写,默认是首页,一般是index.html

查询字符串

针对已指定的文件路径内的资源,可以使用查询字符串兑换如任意参数。此项可选。

片段标识符

使用片段标识符通常可标记处已获取资源的子资源(文档内的某个位置)。但是在RFC中没有明确规定其使用方法。该项为可选项

2 HTTP协议

HTTP协议用于客户端和服务器之间的通信。
客户端

请求访问文本或图像等资源的一端称为客户端。

服务端

提供资源响应的一端称为服务端。

2.1 请求报文

下面是HTTP请求的格式:
在这里插入图片描述
真实的请求如下:
在这里插入图片描述
对比一下格式与真实情况:
在这里插入图片描述

2.2 响应报文

下面是HTTP响应的格式:
在这里插入图片描述
真实响应如下:
在这里插入图片描述
下面是对比:
在这里插入图片描述

3 模拟HTTP

下面的代码是socket套接字实现,主要为了http通信提供网络接口。

3.1 Socket.hpp

#pragma once#include <iostream>
#include <string>
#include <unistd.h>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>enum
{SocketErr = 2,BindErr,ListenErr,
};const int backlog = 10;class Sock
{
public:Sock(){}~Sock(){}public:void Socket(){_sockfd = socket(AF_INET, SOCK_STREAM, 0);if (_sockfd < 0){std::cout << "sock error " << strerror(errno) << errno << std::endl;exit(SocketErr);}}void Bind(uint16_t port){struct sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(port);local.sin_addr.s_addr =INADDR_ANY;if (bind(_sockfd, (struct sockaddr*)&local, sizeof(local)) < 0){std::cout << "bind error " << strerror(errno) << errno << std::endl;exit(BindErr);}}void Listen(){if (listen(_sockfd, backlog) < 0){std::cout << "listen error " << strerror(errno) << errno << std::endl;exit(ListenErr);}}int Accept(std::string *clientip, uint16_t *clientport){struct sockaddr_in peer;socklen_t len = sizeof(peer);int newfd = accept(_sockfd, (struct sockaddr*)& peer, &len);if (newfd < 0){std::cout << "accept error " << strerror(errno) << errno << std::endl;return -1;}char ipstr[64];inet_ntop(AF_INET, &peer.sin_addr, ipstr, sizeof(ipstr));*clientip = ipstr;*clientport = ntohs(peer.sin_port);return newfd; }bool Connnect(const std::string &ip, const uint16_t &port){struct sockaddr_in peer;memset(&peer, 0, sizeof(peer));peer.sin_family =AF_INET;peer.sin_port = htons(port);inet_pton(AF_INET, ip.c_str(), &(peer.sin_addr));int n = connect(_sockfd, (struct sockaddr*)&peer, sizeof(peer));if (n == -1){std::cout << "connect to" << ip << " : " << port << " error "  << std::endl;return false;}return true;}void Close(){close(_sockfd);}int Fd(){return _sockfd;}private://文件描述符int _sockfd;  
};

3.2 HttpServer.hpp

class HttpServer
{
public:HttpServer(int port = defaultport):_port(defaultport){}
private:Sock _listensock;uint16_t _port;
};

模拟的是使用HTTP协议的过程,客户端需要向浏览器访问,
输入的内容为ip:port。 例如:http://124.223.90.51:8085

因此,需要创建一个函数来启动HTTP服务器:

3.2.1 start()

    bool Start(){//创建套接字_listensock.Socket();_listensock.Bind(_port);_listensock.Listen();for (;;){std::string clientip;uint16_t clientport;int sockfd = _listensock.Accept(&clientip, &clientport);pthread_t tid;ThreadData *td = new ThreadData(sockfd, this);td->sockfd = sockfd;pthread_create(&tid, nullptr, ThreadRun, td);}}   

1.创建监听套接字

_listensock.Socket();  
_listensock.Bind(_port);
_listensock.Listen();
  • _listensock.Socket():创建 TCP 套接字(socket())。
  • _listensock.Bind(_port):绑定端口 _port(bind())。
  • _listensock.Listen():监听端口,等待客户端连接(listen())。

作用:服务器启动,监听 _port 端口,准备接受 HTTP 请求。.

2.接受客户端连接

int sockfd = _listensock.Accept(&clientip, &clientport);
  • Accept():阻塞等待客户端连接,成功返回新连接的套接字 sockfd,并获取客户端的 IP 和端口。
  • 客户端访问 http://服务器IP:端口,就会触发 Accept()。

作用:获取客户端连接,并准备创建线程处理。.

3.创建新线程处理客户端请求

pthread_t tid;
ThreadData *td = new ThreadData(sockfd, this);
td->sockfd = sockfd;
pthread_create(&tid, nullptr, ThreadRun, td);
  • 创建 ThreadData 结构体,存储 sockfd 和 this(服务器指针)。
  • pthread_create()创建新线程 ThreadRun(td),让线程处理 sockfd 连接。

作用:服务器为每个客户端请求创建一个新线程并行处理,提高并发能力。.

3.2.2 ThreadRun()

    static void* ThreadRun(void* args){pthread_detach(pthread_self());ThreadData *td = static_cast<ThreadData*>(args);// char buffer[10240];// //ssize_t n = read(?; buffer, sizeof(buffer - 1));  可以使用read// //也可以使用recv// ssize_t n = recv(td->sockfd, buffer, sizeof(buffer - 1), 0);// if (n > 0)// {//     buffer[n] = 0;//     std::cout << buffer;// }HandlerHttp(td->sockfd, td->httpsvr);delete td;return nullptr;}
  • 这段代码是 HttpServer 服务器每个新线程的执行函数 ThreadRun(),用于处理客户端的 HTTP 请求。

  • 当客户端连接服务器时,服务器会创建一个新线程执行 ThreadRun(),读取 HTTP 请求并进行处理。

pthread_detach(pthread_self()) 作用:

  • 让线程在完成后自动释放资源,不需要 pthread_join() 手动回收。
  • 避免僵尸线程(已结束但未回收的线程)。
  • 适用于短生命周期的线程,如 HTTP 服务器的请求处理线程。

为什么要线程分离 ?

  • HTTP 请求通常是短暂的,处理完成后线程就不需要存在了。
  • 如果不分离,主线程需要 pthread_join() 逐个回收,会浪费资源。
  • 让线程自动销毁,提高服务器并发能力

为什么ThreadRun被设置为static?

  1. pthread_create() 需要一个 C 语言风格的函数指针

pthread_create的函数签名如下:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
  • 第三个参数 start_routine 是一个函数指针,必须符合 void* ()(void) 这种标准格式。

  • 普通成员函数有一个隐藏的 this 指针,无法直接传递给 pthread_create()。

所以,必须用:
普通的 C 函数(static 成员函数), 或全局函数

3.2.3 HandlerHttp()

static void HandlerHttp(int sockfd, HttpServer *httpsvr){char buffer[10240];ssize_t n = recv(sockfd, buffer, sizeof(buffer) - 1, 0);   //在这里,不能保证读到了完整的http请求if (n > 0){buffer[n] = 0;std::cout << buffer << std::endl;  //假设我们读到的是一个完整的http请求HttpRequest req;req.Deserialize(buffer);req.Parse();std::string text;bool ok = true; text = ReadHtmlContent(req.file_path);  //读取客户端请求的文件 --> "./index.html"if (text.empty()){ok = false;std::string err_html = wwwroot;err_html += "/";err_html += "err.html";text = ReadHtmlContent(err_html);}//返回响应的过程std::string response_lines;if (ok){response_lines = "HTTP/1.0 200 OK\r\n";}else {response_lines = "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: text/html\r\n";response_header += "\r\n";response_header += "Set-Cookie : name=haha&&passds=12345";response_header += "\r\n";std::string blank_lines = "\r\n";std::string response = response_lines;response += response_header;response += blank_lines;response += text;//将内容发送给客户端  -- 响应send(sockfd, response.c_str(), response.size(), 0);}close(sockfd);}

HandlerHttp函数的作用是处理HTTP请求并返回响应

HandlerHttp() 的作用是 处理 HTTP 请求并返回响应,它是 HTTP 服务器的核心逻辑,负责:

  1. 读取客户端请求数据
  2. 解析 HTTP 请求
  3. 获取请求的资源(如 HTML 页面)
  4. 构造 HTTP 响应
  5. 将 HTTP 响应返回给客户端
  6. 关闭连接

1. 如何解析HTTP请求?
根据前文所说,HTTP请求格式如下:
在这里插入图片描述
可以看到,HTTP请求是一个已经序列化的报文,因此,我们如果想要知道具体的Method, URI,Http_Version就必须进行反序列化。

void Deserialize(std::string req)
{while(true){ssize_t pos = req.find(seq);  // 找到 "\r\n" 的位置if (pos == std::string::npos) // 没有找到 "\r\n",说明 HTTP 头部已经解析完毕break;std::string temp = req.substr(0, pos);  // 提取一行 HTTP 头部信息if (temp.empty()) // 如果这一行是空的,说明遇到了 HTTP 头部和正文的分隔行break;req_header.push_back(temp);  // 将解析出的头部信息存入 `req_header`req.erase(0, pos + seq.size());  // 删除已经解析的部分,继续处理剩下的内容}// req 现在去掉了所有头部,剩下的就是 HTTP 请求的正文text = req;
}

假设客户端发送了如下 HTTP 请求:
在这里插入图片描述
那么req_header 里的内容:
在这里插入图片描述
经过反序列化之后,req_header的内容如下:

req_header[0] = “GET /index.html HTTP/1.1”
req_header[1] = “Host: 124.223.90.51:8085”

text = “name=hello&password=1234”;

2. 如何获取Method/URI/Http_Version?

std::stringstream ss(req_header[0]);  
ss >> method >> url >> http_version;

① std::stringstream ss(req_header[0])

  • std::stringstream 是 C++ 的 字符串流(string stream),类似 std::cin,可以像读取标准输入一样 按空格分割字符串。
  • 这里 req_header[0]"GET /index.html HTTP/1.1",将其存>入 ss 后,ss 变成了一个可以逐个提取单词的输入流。

② ss >> method >> url >> http_version;

  • ss >> method → 提取 “GET”,存入 method。
  • ss >> url → 提取 “/index.html”,存入 url。
  • ss >> http_version → 提取 “HTTP/1.1”,存入 http_version。

最终:
在这里插入图片描述

3. 如何根据客户端的输入确定要访问哪个文件?

首先定义:

const std::string wwwroot = "./wwwroot";

./wwwroot路径是HTTP的根目录,所有的文件都放在根目录下,如果客户端不指定访问具体的哪个文件,那么默认访问根目录。

        file_path = wwwroot;if (url == "/" || url == "/index.html")  //根目录{file_path += "/";file_path += homepage;}else{file_path += url;}

通过上面的代码确定file_path的值,也就可以精准访问到具体的文件。

4. 如何读取html文件的内容?

之前确定了file_path的值,也就是确定了读取的具体的文件,接下来就是进入到文件内部读取文件的内容。

std::ifstream in(htmlpath, std::ios::binary);
  • std::ifstream 打开文件,std::ios::binary 以 二进制模式 读取(防止换行符转换)。
  • 如果 htmlpath 指定的文件 不存在或打不开,流对象 in 不会打开。
in.seekg(0, std::ios_base::end);
auto len = in.tellg();
in.seekg(0, std::ios_base::beg);
  • seekg(0, std::ios_base::end); → 将文件指针移动到文件末尾,这样 tellg() 可以获取 文件大小。
  • len = in.tellg(); → 获取文件的长度(字节数)。
  • seekg(0, std::ios_base::beg); → 将文件指针移动回文件开头,准备读取内容。
std::string content;
content.resize(len);
  • 创建字符串 content,并分配 len 个字符的空间,以存放 HTML 文件的内容。
in.read((char*)content.c_str(), content.size());
  • 读取文件内容到 content:
  • in.read() 读取 content.size() 个字符,并存入 content 中。
  • content.c_str() 获取 std::string 的底层 C 风格字符数组的指针,保证数据存储正确

5. 为什么要采用二进制的读法?

因为读取的不一定是html文件,有可能是图片,视频。如果是普通的read方法,可能无法读取图片资源。

6. 如何返回HTTP响应?
在这里插入图片描述
1. 根据读到的内容判断状态码:

if (text.empty()){ok = false;std::string err_html = wwwroot;err_html += "/";err_html += "err.html";text = ReadHtmlContent(err_html);}//返回响应的过程std::string response_lines;if (ok){response_lines = "HTTP/1.0 200 OK\r\n";}else {response_lines = "HTTP/1.0 404 Not Found\r\n";}

2. 添加Key:Value部分:

            std::string response_header = "Content-Length: ";response_header += std::to_string(text.size());response_header += "\r\n";response_header += "Content-Type: text/html\r\n";response_header += "\r\n";response_header += "Set-Cookie : name=haha&&passds=12345";response_header += "\r\n";

3.添加空行部分

std::string blank_lines = "\r\n";

4.整理所有的内容返回给客户端

            std::string response = response_lines;response += response_header;response += blank_lines;response += text;//将内容发送给客户端  -- 响应send(sockfd, response.c_str(), response.size(), 0);

总结

HttpServer.hpp的内容如下:

#pragma once#include <iostream>
#include <pthread.h>
#include "Socket.hpp"
#include <string>
#include <vector>
#include <fstream>
#include <sstream>static const int defaultport = 8085;const std::string seq = "\r\n";
const std::string wwwroot = "./wwwroot";
const std::string homepage = "index.html";class HttpServer;class ThreadData
{
public:ThreadData(int fd, HttpServer *ts):sockfd(fd),httpsvr(ts){}
public:int sockfd;HttpServer *httpsvr;
};class HttpRequest
{
public://反序列化 -- 将从客户端读到的http请求push_back进req_header中void Deserialize(std::string req){while(true){ssize_t pos = req.find(seq);if (pos == std::string::npos)break;std::string temp = req.substr(0, pos);if (temp.empty())break;req_header.push_back(temp);req.erase(0, pos + seq.size());}//req去掉前面的内容之后,剩下的全是文本text = req;}void DebugPrint(){for (auto &line : req_header){std::cout << "-------------------" << std::endl;std::cout << line << "\n\n";}std::cout << "method : " << method << std::endl;std::cout << "url : " << url << std::endl;std::cout << "http version : " << http_version << std::endl;std::cout << "file path : " << file_path << std::endl;std::cout << "text : " << text << std::endl;}void Parse(){std::stringstream ss(req_header[0]);ss >> method >> url >> http_version;   //用stringstream将method等直接分割了file_path = wwwroot;if (url == "/" || url == "/index.html")  //根目录{file_path += "/";file_path += homepage;}else{file_path += url;}// auto pos = file_path.rfind(".");// if (pos == std::string::npos)}
public:std::vector<std::string> req_header;  //请求std::string text;//解析之后的结果  --> 这是http的请求报文的格式std::string method;std::string url;std::string http_version;std::string file_path;
};class HttpServer
{
public:HttpServer(int port = defaultport):_port(defaultport){}bool Start(){//创建套接字_listensock.Socket();_listensock.Bind(_port);_listensock.Listen();for (;;){std::string clientip;uint16_t clientport;int sockfd = _listensock.Accept(&clientip, &clientport);pthread_t tid;ThreadData *td = new ThreadData(sockfd, this);td->sockfd = sockfd;pthread_create(&tid, nullptr, ThreadRun, td);}}   static void* ThreadRun(void* args){pthread_detach(pthread_self());ThreadData *td = static_cast<ThreadData*>(args);// char buffer[10240];// //ssize_t n = read(?; buffer, sizeof(buffer - 1));  可以使用read// //也可以使用recv// ssize_t n = recv(td->sockfd, buffer, sizeof(buffer - 1), 0);// if (n > 0)// {//     buffer[n] = 0;//     std::cout << buffer;// }HandlerHttp(td->sockfd, td->httpsvr);delete td;return nullptr;}//固定版本// static void HanderHttp(int sockfd, HttpServer *httpsvr)// {//     char buffer[10240];//     ssize_t n = recv(sockfd, buffer, sizeof(buffer) - 1, 0);   //在这里,不能保证读到了完整的http请求//     if (n > 0)//     {//         buffer[n] = 0;//         std::cout << buffer;//         //返回相应的过程//         std::string text = "mayue is a pig! xixi~";//         std::string response_lines = "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_lines = "\r\n";//         std::string response = response_lines;//         response += response_header;//         response += blank_lines;//         response += text;//         //将内容发送给发送方  -- 响应//         send(sockfd, response.c_str(), response.size(), 0);//     }//     close(sockfd);// }//读取文件内容static std::string ReadHtmlContent(const std::string &htmlpath){std::ifstream in(htmlpath, 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;}//显示不同的html,进行处理static void HandlerHttp(int sockfd, HttpServer *httpsvr){char buffer[10240];ssize_t n = recv(sockfd, buffer, sizeof(buffer) - 1, 0);   //在这里,不能保证读到了完整的http请求if (n > 0){buffer[n] = 0;std::cout << buffer << std::endl;  //假设我们读到的是一个完整的http请求HttpRequest req;req.Deserialize(buffer);req.Parse();std::string text;bool ok = true; text = ReadHtmlContent(req.file_path);  //读取客户端请求的文件 --> "./index.html"if (text.empty()){ok = false;std::string err_html = wwwroot;err_html += "/";err_html += "err.html";text = ReadHtmlContent(err_html);}//返回响应的过程std::string response_lines;if (ok){response_lines = "HTTP/1.0 200 OK\r\n";}else {response_lines = "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: text/html\r\n";response_header += "\r\n";response_header += "Set-Cookie : name=haha&&passds=12345";response_header += "\r\n";std::string blank_lines = "\r\n";std::string response = response_lines;response += response_header;response += blank_lines;response += text;//将内容发送给客户端  -- 响应send(sockfd, response.c_str(), response.size(), 0);}close(sockfd);}~HttpServer(){}private:Sock _listensock;uint16_t _port;
};

HttpServer.cc

#include "Httpserver.hpp"
#include <iostream>
#include <memory>using namespace std;int main()
{//std::unique<HttpServer> svr(new HttpServer());HttpServer *svr = new HttpServer();svr->Start();return 0;
}

在这里插入图片描述

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

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

相关文章

数据分析师使用Kutools for Excel 插件

数据分析师使用Kutools for Excel 插件 Kutools for Excel 是一款功能强大的 Excel 插件&#xff0c;旨在提高 Excel 用户的工作效率&#xff0c;简化复杂的操作。它提供了超过 300 个增强功能&#xff0c;帮助用户快速完成数据管理、格式化、排序、分析等任务&#xff0c;特别…

ElasticStack简介及应用

文章目录 1.Elastic Stack 技术栈2.ES 安装2.1 准备2.2 yum单机部署2.3 集群部署 3.Kibana3.1 安装配置3.2 web访问 4.Filebeat4.1 安装4.2 配置 inputs4.3 配置 output4.4 索引4.5 分片和副本 5.收集nginx日志5.1 原生日志5.2 nginx日志格式5.3 filebeat 配置 6.logstash6.1 安…

解决Mac安装软件的“已损坏,无法打开。 您应该将它移到废纸篓”问题

mac安装软件时&#xff0c;如果出现这个问题&#xff0c;其实很简单 首先打开终端&#xff0c;输入下面的命令 sudo xattr -r -d com.apple.quarantine 输入完成后&#xff0c;先不要回车&#xff0c;点击访达--应用程序--找到你无法打开的app图标&#xff0c;拖到终端窗口中…

pytorch实现长短期记忆网络 (LSTM)

人工智能例子汇总&#xff1a;AI常见的算法和例子-CSDN博客 LSTM 通过 记忆单元&#xff08;cell&#xff09; 和 三个门控机制&#xff08;遗忘门、输入门、输出门&#xff09;来控制信息流&#xff1a; 记忆单元&#xff08;Cell State&#xff09; 负责存储长期信息&…

后盾人JS--继承

继承是原型的继承 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </hea…

实际操作 检测缺陷刀片

号he 找到目标图像的缺陷位置&#xff0c;首先思路为对图像进行预处理&#xff0c;灰度-二值化-针对图像进行轮廓分析 //定义结构元素 Mat se getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1)); morphologyEx(thre, tc, MORPH_OPEN, se, Point(-1, -1), 1); …

从实数与复数在交流电路正弦量表示中的对比分析

引言 在交流电路领域&#xff0c;深入理解电压和电流等正弦量的表示方式对电路分析至关重要。其中&#xff0c;只用实数表示正弦量存在诸多局限性&#xff0c;而复数的引入则为正弦量的描述与分析带来了极大的便利。下面将从瞬时值角度&#xff0c;详细剖析只用实数的局限性&a…

Python3 OS模块中的文件/目录方法说明十四

一. 简介 前面文章简单学习了 Python3 中 OS模块中的文件/目录的部分函数。 本文继续来学习 OS 模块中文件、目录的操作方法&#xff1a;os.statvfs() 方法&#xff0c;os.symlink() 方法。 二. Python3 OS模块中的文件/目录方法 1. os.statvfs() 方法 os.statvfs() 方法用…

知识蒸馏教程 Knowledge Distillation Tutorial

来自于&#xff1a;Knowledge Distillation Tutorial 将大模型蒸馏为小模型&#xff0c;可以节省计算资源&#xff0c;加快推理过程&#xff0c;更高效的运行。 使用CIFAR-10数据集 import torch import torch.nn as nn import torch.optim as optim import torchvision.tran…

Turing Complete-1位开关

要求如下&#xff1a; 我的思考&#xff1a; 把输入1当作控制信号&#xff0c;把输入2当作输出信号。 通过非门和开关使输入2形成双通道输出&#xff0c; 通道一为输出输入2取反。 通道二为输出输入2本身。 通过输入1来控制两个通道的开闭。

从Transformer到世界模型:AGI核心架构演进

文章目录 引言:架构革命推动AGI进化一、Transformer:重新定义序列建模1.1 注意力机制的革命性突破1.2 从NLP到跨模态演进1.3 规模扩展的黄金定律二、通向世界模型的关键跃迁2.1 从语言模型到认知架构2.2 世界模型的核心特征2.3 混合架构的突破三、构建世界模型的技术路径3.1 …

深度求索DeepSeek横空出世

真正的强者从来不是无所不能&#xff0c;而是尽我所能。多少有关输赢胜负的缠斗&#xff0c;都是直面本心的搏击。所有令人骄傲振奋的突破和成就&#xff0c;看似云淡风轻寥寥数语&#xff0c;背后都是数不尽的焚膏继晷、汗流浃背。每一次何去何从的困惑&#xff0c;都可能通向…

性能优化中的数据过滤优化

目录 以下是一些关于数据过滤优化的策略和方法 索引使用 避免全表扫描 使用分区 数据预处理 合理设计查询 利用缓存机制 数据库层面优化 系统中通常会有一些统计和分析的功能&#xff0c;以前我们主要针对结构化数据&#xff08;关系型数据库存储&#xff09;进行分析&a…

与本地Deepseek R1:14b的第一次交流

本地部署DS的方法&#xff0c;见&#xff1a;本地快速部署DeepSeek-R1模型——2025新年贺岁-CSDN博客 只有16GB内存且没有强大GPU的个人电脑&#xff0c;部署和运行14b参数的DS大模型已是天花板了。 运行模型 ollama run deepseek-r1:14b C:\Users\Administrator>ollama r…

Python 梯度下降法(六):Nadam Optimize

文章目录 Python 梯度下降法&#xff08;六&#xff09;&#xff1a;Nadam Optimize一、数学原理1.1 介绍1.2 符号定义1.3 实现流程 二、代码实现2.1 函数代码2.2 总代码 三、优缺点3.1 优点3.2 缺点 四、相关链接 Python 梯度下降法&#xff08;六&#xff09;&#xff1a;Nad…

【狂热算法篇】探秘图论之Dijkstra 算法:穿越图的迷宫的最短路径力量(通俗易懂版)

羑悻的小杀马特.-CSDN博客羑悻的小杀马特.擅长C/C题海汇总,AI学习,c的不归之路,等方面的知识,羑悻的小杀马特.关注算法,c,c语言,青少年编程领域.https://blog.csdn.net/2401_82648291?typebbshttps://blog.csdn.net/2401_82648291?typebbshttps://blog.csdn.net/2401_8264829…

MySQL(Undo日志)

后面也会持续更新&#xff0c;学到新东西会在其中补充。 建议按顺序食用&#xff0c;欢迎批评或者交流&#xff01; 缺什么东西欢迎评论&#xff01;我都会及时修改的&#xff01; 大部分截图和文章采用该书&#xff0c;谢谢这位大佬的文章&#xff0c;在这里真的很感谢让迷茫的…

全面剖析 XXE 漏洞:从原理到修复

目录 前言 XXE 漏洞概念 漏洞原理 XML 介绍 XML 结构语言以及语法 XML 结构 XML 语法规则 XML 实体引用 漏洞存在原因 产生条件 经典案例介绍分析 XXE 漏洞修复方案 结语 前言 网络安全领域暗藏危机&#xff0c;各类漏洞威胁着系统与数据安全。XXE 漏洞虽不常见&a…

初级数据结构:栈和队列

目录 一、栈 (一)、栈的定义 (二)、栈的功能 (三)、栈的实现 1.栈的初始化 2.动态扩容 3.压栈操作 4.出栈操作 5.获取栈顶元素 6.获取栈顶元素的有效个数 7.检查栈是否为空 8.栈的销毁 9.完整代码 二、队列 (一)、队列的定义 (二)、队列的功能 (三&#xff09…

登录认证(5):过滤器:Filter

统一拦截 上文我们提到&#xff08;登录认证&#xff08;4&#xff09;&#xff1a;令牌技术&#xff09;&#xff0c;现在大部分项目都使用JWT令牌来进行会话跟踪&#xff0c;来完成登录功能。有了JWT令牌可以标识用户的登录状态&#xff0c;但是完整的登录逻辑如图所示&…