【网络】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?
- 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 服务器的核心逻辑,负责:
- 读取客户端请求数据
- 解析 HTTP 请求
- 获取请求的资源(如 HTML 页面)
- 构造 HTTP 响应
- 将 HTTP 响应返回给客户端
- 关闭连接
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;
}
相关文章:
【网络】3.HTTP(讲解HTTP协议和写HTTP服务)
目录 1 认识URL1.1 URI的格式 2 HTTP协议2.1 请求报文2.2 响应报文 3 模拟HTTP3.1 Socket.hpp3.2 HttpServer.hpp3.2.1 start()3.2.2 ThreadRun()3.2.3 HandlerHttp() 总结 1 认识URL 什么是URI? URI 是 Uniform Resource Identifier的缩写&…...
mysql_init和mysql_real_connect的形象化认识
解析总结 1. mysql_init 的作用 mysql_init 用于初始化一个 MYSQL 结构体,为后续数据库连接和操作做准备。该结构体存储连接配置及状态信息,是 MySQL C API 的核心句柄。 示例: MYSQL *conn mysql_init(NULL); // 初始化连接句柄2. mysql_…...
01.01、判定字符是否唯一
01.01、[简单] 判定字符是否唯一 1、题目描述 实现一个算法,确定一个字符串 s 的所有字符是否全都不同。 在这一题中,我们的任务是判断一个字符串 s 中的所有字符是否全都不同。我们将讨论两种不同的方法来解决这个问题,并详细解释每种方法…...
[NOIP2007]矩阵取数游戏
点我写题 题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数。游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有元素; 2.每次取走的…...
C++模板初识
文章目录 一、函数模板1. 函数模板2. 函数模板、模板的特例化、非模板函数的重载关系3. 外部调用4. 模板的非类型参数5. 代码示例 二、类模板 一、函数模板 1. 函数模板 模板函数:在函数调用点,编译器用用户指定的类型,从原模板实例化一份函…...
C# Winform制作一个登录系统
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace 登录 {p…...
Kafka常见问题之 org.apache.kafka.common.errors.RecordTooLargeException
文章目录 Kafka常见问题之 org.apache.kafka.common.errors.RecordTooLargeException: The message is 1,048,576 bytes when serialized which is larger than the maximum request size.1. 错误解析2. 错误原因3. 错误复现案例3.1 生产者发送超大消息 4. 解决方案4.1 方法 1&…...
Python | Pytorch | Tensor知识点总结
如是我闻: Tensor 是我们接触Pytorch了解到的第一个概念,这里是一个关于 PyTorch Tensor 主题的知识点总结,涵盖了 Tensor 的基本概念、创建方式、运算操作、梯度计算和 GPU 加速等内容。 1. Tensor 基本概念 Tensor 是 PyTorch 的核心数据结…...
arm-linux-gnueabihf安装
Linaro Releases windows下打开wsl2中的ubuntu,资源管理器中输入: \\wsl$gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz 复制到/home/ark01/tool 在 Ubuntu 中创建目录: /usr/local/arm,命令如下: …...
C++ 堆栈分配的区别
这两种声明方式有什么区别 1.使用 new 关键字动态分配内存 动态分配:使用 new 关键字会在堆(heap)上分配内存,并返回一个指向该内存位置的指针。生命周期:对象的生命周期不会随着声明它的作用域结束而结束࿰…...
大数据相关职位 职业进阶路径
大数据相关职位 & 职业进阶路径 📌 大数据相关职位 & 职业进阶路径 大数据领域涵盖多个方向,包括数据工程、数据分析、数据治理、数据科学等,每个方向的进阶路径有所不同。以下是大数据相关职位的详细解析及其职业进阶关系。 &#…...
【计算机网络】设备更换地区后无法访问云服务器问题
文章目录 1. **服务器的公网 IP 是否变了**2. **服务器的防火墙或安全组设置**3. **本地运营商或 NAT 限制**4. **ISP 限制或端口封锁**5. **服务器监听地址检查** 1. 服务器的公网 IP 是否变了 在服务器上运行以下命令,检查当前的公网 IP:curl ifconfi…...
STM32标准库移植RT-Thread nano
STM32标准库移植RT-Thread Nano 哔哩哔哩教程链接:STM32F1标准库移植RT_Thread Nano 移植前的准备 stm32标准库的裸机代码(最好带有点灯和串口)RT-Thread Nano Pack自己的开发板 移植前的说明 本人是在读学生,正在学习阶段&a…...
【C++题解】1055. 求满足条件的整数个数
欢迎关注本专栏《C从零基础到信奥赛入门级(CSP-J)》 问题:1055. 求满足条件的整数个数 类型:简单循环 题目描述: 在 1∼n 中,找出能同时满足用 3 除余 2 ,用 5 除余 3 ,用 7 除余…...
DeepSeek R1-Zero vs. R1:强化学习推理的技术突破与应用前景
📌 引言:AI 推理的新时代 近年来,大语言模型(LLM) 的规模化扩展成为 AI 研究的主流方向。然而,LLM 的扩展是否真的能推动 通用人工智能(AGI) 的实现?DeepSeek 推出的 R1…...
冲刺蓝桥杯之速通vector!!!!!
文章目录 知识点创建增删查改 习题1习题2习题3习题4:习题5: 知识点 C的STL提供已经封装好的容器vector,也可叫做可变长的数组,vector底层就是自动扩容的顺序表,其中的增删查改已经封装好 创建 const int N30; vecto…...
【视频+图文详解】HTML基础1-html和css介绍、上网原理
图文详解 html介绍 概念:html是超文本标记语言的缩写,其英文全称为HyperText Markup Language,是用来搭建网站结构的语言,比如网页上的文字,按钮,图片,视频等。html的版本分为1.0、2.0、3.0、…...
Deepseek技术浅析(二):大语言模型
DeepSeek 作为一家致力于人工智能技术研发的公司,其大语言模型(LLM)在架构创新、参数规模扩展以及训练方法优化等方面都达到了行业领先水平。 一、基于 Transformer 架构的创新 1.1 基础架构:Transformer 的回顾 Transformer 架…...
OpenCV 版本不兼容导致的问题
问题和解决方案 今天运行如下代码,发生了意外的错误,代码如下,其中输入的 frame 来自于 OpenCV 开启数据流的读取 """ cap cv2.VideoCapture(RTSP_URL) print("链接视频流完成") while True:ret, frame cap.rea…...
03.04、化栈为队
03.04、化栈为队 1、题目描述 实现一个 MyQueue 类,该类用两个栈来实现一个队列。 2、解题思路 本题要求使用两个栈来实现一个队列。队列遵循先进先出(FIFO)的原则,而栈遵循后进先出(LIFO)的原则。因此…...
[Effective C++]条款49-52 内存分配
本文初发于 “天目中云的小站”,同步转载于此。 条款49 : 了解new-handler的行为 条款50 : 了解new和delete的合理替换时机 条款51 : 编写new和delete时需固守常规 条款52 :写了placement new也要写placement delete 条款49-52中详细讲述了定制new和d…...
vue3的路由配置
先找到Layout布局文件,从中找到左侧边栏,找到下述代码 <SidebarItem v-for"route in noHiddenRoutes" :key"route.path" :item"route" :base-path"route.path" />/** *菜单项 <SidebarItem>: *使用…...
基于AnolisOS 8.6安装GmSSL 3.1.1及easy_gmssl库测试国密算法
测试环境 Virtual Box,AnolisOS-8.6-x86_64-minimal.iso,4 vCPU, 8G RAM, 60 vDisk。最小化安装。需联网。 系统环境 关闭防火墙 systemctl stop firewalld systemctl disable firewalld systemctl status firewalld selinux关闭 cat /etc/selinux/co…...
Linux系统:Ubuntu替换镜像源具体方法;
在Linux系统更新下载软件时,如遇因镜像源问题下载失败时,我们就需要替换系统原有镜像源,那么,此时,你是否还在百度四处搜索可以用的镜像源地址,然后反复去测试源地址的正确性呢,下面介绍一个亲测…...
机器人介绍
以下是关于机器人的介绍: 定义 机器人是一种能够自动执行任务的机器系统,它集成了机电、机构学、材料学及仿生学等多个学科技术,可以接受人类指挥,运行预先编排的程序,或根据人工智能技术制定的原则纲领行动…...
thinkphp6+swoole使用rabbitMq队列
安装think-swoole安装 composer require php-amqplib/php-amqplib,以支持rabbitMq使用安装rabbitMq延迟队列插件 安装 rabbitmq_delayed_message_exchange 插件,按照以下步骤操作: 下载插件:https://github.com/rabbitmq/rabbitmq-delayed-…...
19.Word:小马-校园科技文化节❗【36】
目录 题目 NO1.2.3 NO4.5.6 NO7.8.9 NO10.11.12索引 题目 NO1.2.3 布局→纸张大小→页边距:上下左右插入→封面:镶边→将文档开头的“黑客技术”文本移入到封面的“标题”控件中,删除其他控件 NO4.5.6 标题→原文原文→标题 正文→手…...
Pandas进行MongoDB数据库CRUD
在数据处理的领域,MongoDB作为一款NoSQL数据库,以其灵活的文档存储结构和高扩展性广泛应用于大规模数据处理场景。Pandas作为Python的核心数据处理库,能够高效处理结构化数据。在MongoDB中,数据以JSON格式存储,这与Pandas的DataFrame结构可以很方便地互相转换。通过这篇教…...
分布式系统相关面试题收集
目录 什么是分布式系统,以及它有哪些主要特性? 分布式系统中如何保证数据的一致性? 解释一下CAP理论,并说明在分布式系统中如何权衡CAP三者? 什么是分布式事务,以及它的实现方式有哪些? 什么是…...
家居EDI:Hom Furniture EDI需求分析
HOM Furniture 是一家成立于1977年的美国家具零售商,总部位于明尼苏达州。公司致力于提供高品质、时尚的家具和家居用品,满足各种家庭和办公需求。HOM Furniture 以广泛的产品线和优质的客户服务在市场上赢得了良好的口碑。公司经营的产品包括卧室、客厅…...
原码、反码、补码以及lowbit运算
原码、反码、补码以及lowbit运算 原码: 可以用来计算正数加减,正数的原码、反码、补码都一样。 第一位为符号位,符号位0为正数,1为负数(32位字符,这里用4位来举例子,后面皆是用4位来举例子,其…...
iOS 集成ffmpeg
前言 本来打算用flutter去实现一个ffmpeg的项目的,不过仔细分析了一下,我后期需要集成OpenGL ES做视频渲染处理,OpenGL ES的使用目前在flutter上面还不是很成熟,所以最后还是选择用原生来开发 ffmpeg集成到iOS工程 iOS对于ffmp…...
DeepSeek的崛起与全球科技市场的震荡
引言 近年来,人工智能(AI)技术的快速发展不断重塑全球科技格局。 近日,中国初创企业DeepSeek推出了一款据称成本极低且性能强大的AI模型,引发全球市场的剧烈反应。NVIDIA、台积电等半导体和AI科技巨头股价大幅下跌&am…...
selenium定位网页元素
1、概述 在使用 Selenium 进行自动化测试时,定位网页元素是核心功能之一。Selenium 提供了多种定位方法,每种方法都有其适用场景和特点。以下是通过 id、linkText、partialLinkText、name、tagName、xpath、className 和 cssSelector 定位元素的…...
Elasticsearch有哪些应用场景?
Elasticsearch的应用场景非常广泛,以下是一些主要的应用场景: 1.全文搜索: Elasticsearch凭借其强大、可扩展和快速的搜索功能,在全文搜索场景中表现出色。它允许用户以近乎实时的响应执行复杂的查询,常用于大型网站…...
MySQL 基础学习(1):数据类型与操作数据库和数据表
MySQL 基础学习:数据类型与操作数据库和数据表 在这篇博客中,我们将深入学习 MySQL 的基础操作,重点关注数据库和数据表的操作,以及 MySQL 中常见的数据类型。希望本文能帮助你更好地理解和掌握 MySQL 的基本用法。 一、操作数据…...
芯片AI深度实战:基础篇之Ollama
有这么多大模型,怎么本地用? Ollama可以解决这一问题。不依赖GPU,也不需要编程。就可以在CPU上运行自己的大模型。 软件甚至不用安装,直接在ollama官网下载可执行文件即可。 现在最流行的deepseek-r1也可以使用。当然还有我认为最…...
安卓(android)订餐菜单【Android移动开发基础案例教程(第2版)黑马程序员】
一、实验目的(如果代码有错漏,可查看源码) 1.掌握Activity生命周的每个方法。 2.掌握Activity的创建、配置、启动和关闭。 3.掌握Intent和IntentFilter的使用。 4.掌握Activity之间的跳转方式、任务栈和四种启动模式。 5.掌握在Activity中添加…...
deb安装失败后,无法再安装别的包的解决方案
把package_name换成出安装问题的包 移除该包的安装标记 sudo dpkg --remove --force-remove-reinstreq package_name清理残留文件和配置 sudo apt-get purge package_name...
算法基础学习——二分查找(附带Java模板)
有单调性的数列一定可以使用二分,没有单调性的题目也可能可以使用二分; (一)整数二分 二分的本质: 在某个整数区间内,存在某种性质使得区间内左半边的数都不满足该性质;而右半边的数都满足该性…...
蓝桥杯例题五
无论你面对多大的困难和挑战,都要保持坚定的信念和积极的态度。相信自己的能力和潜力,努力不懈地追求自己的目标和梦想。不要害怕失败,因为失败是成功的垫脚石。相信自己的选择和决策,不要被他人的意见和批评左右。坚持不懈地努力…...
pyside6-uic form.ui -o ui_form.py 的作用
pyside6-uic form.ui -o ui_form.py 的作用 pyside6-uic form.ui -o ui_form.py 这个命令是用来将 .ui 文件转换为 Python 代码文件的工具。 具体作用: pyside6-uic:这是一个命令行工具,用于将用 Qt Designer 或其他图形界面工具创建的 .ui …...
理解神经网络:Brain.js 背后的核心思想
温馨提示 这篇文章篇幅较长,主要是为后续内容做铺垫和说明。如果你觉得文字太多,可以: 先收藏,等后面文章遇到不懂的地方再回来查阅。直接跳读,重点关注加粗或高亮的部分。放心,这种“文字轰炸”不会常有的,哈哈~ 感谢你的耐心阅读!😊 欢迎来到 brain.js 的学习之旅!…...
工业相机开发操作流程
建议按照如下的流程操作相机(其中有一些步骤是可选的,已经标明): 一、载入SDK的动态链接库档MVCAMSDK.DLL。可以使用动态或者静 态加载两种方式。 如果使用C/C进行开发,在工程引用 CameraApi.h头文件(位于安装目录的SDK/DEMO/VC/include中)和…...
利用飞书机器人进行 - ArXiv自动化检索推荐
相关作者的Github仓库 ArXivToday-Lark 使用教程 Step1 新建机器人 根据飞书官方机器人使用手册,新建自定义机器人,并记录好webhook地址,后续将在配置文件中更新该地址。 可以先完成到后续步骤之前,后续的步骤与安全相关&…...
SpringCloudGateWay和Sentinel结合做黑白名单来源控制
假设我们的分布式项目,admin是8087,gateway是8088,consumer是8086 我们一般的思路是我们的请求必须经过我们的网关8088然后网关转发到我们的分布式项目,那我要是没有处理我们绕过网关直接访问项目8087和8086不也是可以࿱…...
Win10安装MySQL、Pycharm连接MySQL,Pycharm中运行Django
一、Windows系统mysql相关操作 1、 检查系统是否安装mysql 按住win r (调出运行窗口) 输入service.msc,点击【确定】 image.png 打开服务列表-检查是否有mysql服务 (compmgmt.msc) image.png 2、 Windows安装MySQL …...
MR-GDINO: Efficient Open-World Continual Object Detection—— 高效开放世界持续目标检测
这篇文章提出了一种名为MR-GDINO的开放世界持续目标检测方法,旨在解决开放世界检测器在持续学习过程中对已见类别和未见类别的灾难性遗忘问题。文章的主要内容和贡献如下: 问题定义:提出了开放世界持续目标检测任务,要求检测器在持…...
显示当前绑定变量
来自v$sql中的信息 测试两个变量的情况(实际可以看6个,可根据需要修改) DROP TABLE T1 PURGE; CREATE TABLE T1 AS SELECT A.*,SYSDATE RIQI FROM DBA_USERS A ORDER BY 1;var mc char(3); var id number; exec :mc:SYS; exec :id:50;set li…...
如何将xps文件转换为txt文件?xps转为pdf,pdf转为txt,提取pdf表格并转为txt
文章目录 xps转txt方法一方法二 pdf转txt整页转txt提取pdf表格,并转为txt 总结另外参考XPS文件转换为TXT文件XPS文件转换为PDF文件PDF文件转换为TXT文件提取PDF表格并转为TXT示例代码(部分) 本文测试代码已上传,路径如下ÿ…...