Linux | 网络通信 | http协议介绍 | cookie策略讲解
文章目录
- url统一资源定位符
- http协议介绍
- GET vs POST
- http状态码
- http常见header
- cookie + session
上篇博客定制了一个协议,该协议用来进行简单的计算,其包含了数据的序列化和反序列化,编码和解码的定制,并且该协议基于TCP通信,是一种客户端请求服务端响应的模型。如果你也实现了一个自己的协议,肯定会有疑问:自己定制的协议不够成熟,而且应用场景有限,有没有一个成熟且应用场景广泛的协议?这还真有,它就是上网必须使用的协议——http,https
url统一资源定位符
要了解http就要先了解url

协议名:表示该url采用的协议
登录信息:一般在url中被隐去,其体现在http请求的报头或者正文当中
服务器地址:也称域名,域名最终会被解析为IP地址
服务器端口号:网络通信的本质是进程间通信,所以需要告知IP+端口号,使通信能够进行。但是由于服务器的端口号通常是固定的,不写端口号时,端口号也能通过其他特殊方法得知,通信照样能进行
文件路径:用具体的路径来表示想要访问服务器的哪些资源
查询字符串:通常用来过滤网页中的信息,得到想要的信息
片段标识符:也称锚点,用来指定网页的停靠位置,或者音视频的播放位置
可以看到,url中不同字段需要用特殊符号进行分隔,这就意味着每一字段中不能出现这些特殊符号,或者说如果出现了这些特殊符号,需要对这些特殊符号做处理。比如搜索c++这这个关键字
由于‘+‘是特殊字符,所以其被编码成其他格式。再者,搜索汉字时,汉字也会被重新编码

虽然url栏显式的是汉字,但是把url复制下来再粘贴,得到的url是
https://www.baidu.com/s?wd=%E5%93%88%E5%93%88
这里说明一下特殊字符的编码规则,将特殊字符转换成十六进制,以两个十六进制数为一组,从低到高一次取出每一组,再它们的前面加上%,编码成%XY的形式。查询ASCII码表,+的码值为43,表示成十六进制是2B,所以在url中,其被编码成%2B

由于url采用的是utf-8编码格式,在该格式下汉字被编码成3个字节,由于两个十六进制数表示1个字节,刚才“哈哈”被编码后,有6组%XY格式的数据,也就是6个字节。关于把特殊字符进行编码的过程,我们叫做urlencode,将%XY格式的数据解码的过程,我们叫做urldecode
再回过头来看url,其全称是Uniform Resource Locator,统一资源定位符,通过url我们就能定位互联网上某一台主机的某些资源。我们使用http协议进行请求,就是请求获取某一天主机(服务器)上的某些资源(音视频,文本),当然,服务器的响应就是将客户端请求获取的资源返回。所以说,我们访问的网页,看到的视频,文字,不是凭空产生的,这些资源都是存储在某些服务器的磁盘上,在我们请求资源时,由服务器发送给我们的。
http协议介绍
比起上篇博客,自己定制的协议,http协议能够使用的场景实在是太多了,同样的,关于http的协议格式也是更复杂的
可以看到http协议格式使用\r\n作为不同字段的分隔符,以http请求为例,在第一个分隔符之前的数据就是http的请求行,里面含有
method:具体http请求的方法,如GET,POST
url:刚才说过的,url用来定位具体资源
http/1.1:http协议的版本
在第一行,请求行之后的字段就是请求报头,其中可能含有客户端主机的信息,连接的属性,有效载荷的长度等等信息,这些信息以key:value的格式保存在报头中,由于这些字段以\r\n分隔,所以可以直观的认为报头的每一行都是一对key:value信息。继续这样进行读取,我们会遇到一个空行,也就是说在报头的最后一个key:value后会有两个\r\n,前一个\r\n用来分隔最后的key:value字段,那么后一个key:value是用来划分有效载荷与报头的,读取http请求时,如果遇到了一个空行,就说明接下来的数据是这次请求的有效载荷了。客户端的请求无非两种,一是请求获取服务端的资源,二是请求将客户端的资源上传到服务端,这些信息都将在有效载荷中体现
至于服务端的响应,其格式与客户端的请求几乎相同,都是三个字段:响应行,响应报头,有效载荷。它们的分隔规则是一样的,不同的是响应行中的数据
http/1.1 状态码 状态码描述
可以看到请求和响应都含有协议的具体版本信息,这样做的目的是:为了使通信能够正常进行,通信双方要保证通信协议版本的一致性,所以客户端和服务端互相发送http协议的版本,如果两者的版本不同,将按照:以较低版本进行通信的原则,进行协议的调整。响应行还包括了状态码和其描述,通常我们请求的网页都是能正常访问的,但是也会有错误情况出现,错误码就表征了请求中的错误,最常见到的错误码就是404,如果你要访问的服务端资源不存在,那么服务端的状态码将被设置为404
GET vs POST
http协议中有很多方法:GET,POST,PUT,DELETE,OPTIONS…其中最经常使用的方法是GET,POST,至于其他方法就较为少见了,如果遇到就现学吧。这里主要说明GET和POST的区别,其中的依据来自
HTTP 方法:GET 对比 POST。首先,GET和POST都是明文传送,两者都是不安全的,使用这两个方法时,我们的数据总是在网络上裸奔,只是方式不同罢了
(在之前的博客中,我搭建了一个TCP网络通信模型,由于http协议是基于tcp的,所以我这里就直接改造这个模型,实现一份服务端代码,对浏览器(客户端)的请求做出响应)
#include <iostream>
#include <string>
#include <stdlib.h>
#include <fstream>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>using namespace std;#define CRLF "\r\n"
#define HOME_PAGE "index.html"
#define ROOT_PAGE "wwwroot"
#define SPACE " "string getPath(const string& req)
{// 请求行的获取size_t head_pos = req.find(CRLF);if (head_pos == string::npos)return "";string head = req.substr(0, head_pos);// 资源路径的获取size_t path_start = head.find(SPACE);size_t path_end = head.rfind(SPACE);if (path_start == string::npos || path_end == string::npos)return "";// 获取资源地址string path = head.substr(path_start + 1, path_end - path_start - 1);// 如果地址为/,默认访问家目录if (path[0] == '/' && path.size() == 1) path += HOME_PAGE;return path;
}string readFile(const string& path)
{ifstream file(path);if (!file.is_open()) return "404";// 将资源的所有数据返回string line;string content;// 读取整份文件的内容while (file.peek() != EOF){getline(file, line);content += line;}return content;
}// 先获取请求报头中的资源位置
// 读取该资源,将其返回
void handlerRequest(int sock)
{char buf[10240] = {0};ssize_t r_ret = read(sock, buf, sizeof(buf));if (r_ret < 0)cout << "read fail" << endl;else if (r_ret == 0)cout << "client quit" << endl;// 读取成功else{string req_str = buf;// for testcout << req_str << endl;// 获取请求行中的资源string path = getPath(req_str);// 读取客户请求的资源,当前根路径的保存string resource_path = ROOT_PAGE;resource_path += path;// 获取文件资源string resource = readFile(resource_path);string suffix = "";// 获取文件的后缀size_t suffix_pos = resource_path.rfind('.');if (suffix_pos != string::npos)suffix = resource_path.substr(suffix_pos);// 创建响应string response = "HTTP/1.1 200 OK\r\n";// 根据后缀为响应报头添加不同字段if (suffix == ".jpg") response += "Content-type: image/jpeg\r\n";else response += "Content-type: text/html\r\n";// 请求正文长度字段的添加response += ("Content-Length: " + to_string(resource.size()) + "\r\n");response += "\r\n";// 响应正文response += resource;// 向客户端发送响应write(sock, response.c_str(), response.size());}
}class tcpServer
{
public:tcpServer(uint16_t port, std::string ip = "") : _ip(ip), _port(port) {}~tcpServer() {}void init(){// 创建套接字文件_listen_sockfd = socket(AF_INET, SOCK_STREAM, 0);if (_listen_sockfd < 0){std::cerr << "socket: fail" << std::endl;exit(-1);}// 填充套接字信息struct sockaddr_in local;local.sin_family = AF_INET;local.sin_port = htons(_port);_ip.empty() ? local.sin_addr.s_addr = INADDR_ANY : inet_aton(_ip.c_str(), &local.sin_addr);// 将信息绑定到套接字文件中if (bind(_listen_sockfd, (const struct sockaddr *)&local, sizeof(local)) < 0){std::cerr << "bind: fail" << std::endl;exit(-1);}// 至此,套接字创建完成,所有的步骤与udp通信一样// 使套接字进入监听状态if (listen(_listen_sockfd, 5) < 0){std::cerr << "listen: fail" << std::endl;exit(-1);}// 套接字初始化完成std::cout << "listen done" << std::endl;}void loop(){// signal(SIGCHLD, SIG_IGN); // 设置SIGCHLD信号为忽略,这样子进程就会自动释放资源// 创建保存套接字信息的结构体struct sockaddr_in peer;socklen_t peer_len = sizeof(peer);// 接受监听队列中的套接字请求while (true){int server_sockfd = accept(_listen_sockfd, (struct sockaddr *)&peer, &peer_len);if (server_sockfd < 0){std::cerr << "accept: fail" << std::endl;continue;}std::cout << "accept done" << std::endl;// 提取请求方的套接字信息uint16_t peer_port = ntohs(peer.sin_port);std::string peer_ip = inet_ntoa(peer.sin_addr);// 打印请求方的套接字信息std::cout << "accept: " << peer_ip << " [" << peer_port << "]" << std::endl;// 使用孙子进程提供服务// grandparentpid_t id = fork();// 祖父进程if (id == 0){// 父进程pid_t cid = fork();if (cid > 0){// 关闭父进程exit(1);}// 孙子进程,孤儿,由1号进程管理handlerRequest(server_sockfd);}// 阻塞的回收进程资源waitpid(id, nullptr, 0);}}
private:std::string _ip;uint16_t _port;int _listen_sockfd;
};static void Usage(std::string proc)
{std::cerr << "Usage:\n\t" << proc << " port" << std::endl;std::cerr << "example:\n\t" << proc << " 8080\n"<< std::endl;
}int main(int argc, char *argv[])
{if (argc != 2){Usage(argv[0]);exit(0);}uint16_t port = atoi(argv[1]);tcpServer svr(port);svr.init();svr.loop();return 0;
}
tcp通信的部分就不再赘述了。为防止僵尸进程,该通信模型创建孙子进程为客户端提供服务,而退出子进程,使孙子进程成为孤儿进程,由1号进程负责其资源的释放。服务端接收到客户端的请求,会对该请求进行解析,得到请求需要的资源路径,服务端会将该资源返回给客户端。下面这份网页就是服务端默认返回给用户的资源
<!-- index.html -->
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>测试</title>
</head><body><h3>hello my server!</h3><p>我终于测试完了我的代码</p><form action="/a/b/c.html" method="get">Username: <input type="text" name="user"><br>Password: <input type="password" name="passwd"><br><input type="submit" value="Submit"></form>
</body></html>
这个网页中有一个表单,客户可以提交它们的用户名和密码信息,其中action标签表示将这些信息发送到指定网页上(当然是客户端再向服务端发送一次请求了),为了测试简单,这里将信息发送到一个不存在的网页中,我们只观察GET和POST的区别。

注意,服务端接收到客户端的请求后,会将客户端的请求打印出来,方便我们的测试,在浏览器的url中输入IP:port,访问服务
我们输入用户名123,密码456,点击submit按钮,这些数据会被发送到action指定的网页上,并且方法是get

很正常,因为网页不存在,所以返回404。但是我们注意到,输入的用户名和密码在url中以查询字符串的方式显示了出来。
将网页提交数据的方式修改为post,重新运行服务,重新连接到该服务,输入用户名密码,submit


可以看到,用户名和密码没有在url中体现,观察服务端打印的客户端请求,可以看到这些信息出现在请求的正文部分。
总结一下:GET将数据以查询字符串的方式拼接到url中,而POST将数据以正文的方式置于请求中,两者都是明文传输,不同的只是POST较GET更隐蔽一些,但两者在本质上都是不安全的。
http状态码
| 1xx | 信息状态码Informational | 接收的请求正在处理,由于现在的网络响应快,这样的状态码很少使用了 |
|---|---|---|
| 2xx | 成功状态码Success | 请求正常处理完毕 |
| 3xx | 重定向状态码Redirection | 将请求重定向到其他资源上 |
| 4xx | 客户端错误状态码Client Error | 服务器无法处理请求,请求非法 |
| 5xx | 服务端错误状态码Server Error | 服务端运行出错 |
这些状态码也不需要具体记忆,记住几个常用的就行了,比如200(OK),404(Not Found),403(Forbidden),302(Redirect),504(Bad Gateway,服务器访问上游服务器超时)
void for_redirection(int sock)
{char buf[10240] = {0};ssize_t r_ret = read(sock, buf, sizeof(buf));if (r_ret < 0)cout << "read fail" << endl;else if (r_ret == 0)cout << "client quit" << endl;// 读取成功else{string req_str = buf;// 创建响应string response = "HTTP/1.1 302 Moved Temporarily\r\n";// 请求正文长度字段的添加response += "location: https://baike.baidu.com/item/302/878045?fr=aladdin\r\n";response += "\r\n";// 向客户端发送响应write(sock, response.c_str(), response.size());}
}
简单的,将服务端的响应修改,请求行修改为"HTTP/1.1 302 Moved Temporarily\r\n",然后在报头中添加location字段,表示重定向的url,如果服务端只提供以上服务的话,不论客户端向服务端发送什么,客户端都将跳转到location字段的url上。不过关于301和302的区别还是要注意一下的,301是当前资源的永久性转移,而302是资源的临时性转移。如果收藏夹中,有一个url301了,浏览器可能会将该url修改为新的url,而302就不会
http常见header
Content-type:正文数据类型(html/text,image/jpeg)
Content-Length:正文长度
Host:告知服务端,客户端要访问的资源在哪台主机上
User-Agenr:声明用户的操作系统和浏览器版本信息
referer:当前页面是从哪个页面跳转过来了
location:配合3xx使用,指定重定向的url,客户端将访问该url
Cookie:存储用户一些数据,用来进行会话的维持
header就是http中的报头字段,以上展示的是字段中的key,每一字段以key:value的方式呈现
最后还剩一个值得讲解的header:Connection,http1.0的Connection默认为closed,http1.1的Connection默认为keep-alive,一个为短连接一个为长连接。在互联网发展早期,网页中的信息没有现在这么的密集,一次http请求就可以获取完整的网页并呈现给客户。但是随着互联网的发展,网页中的信息越来越多,越来越复杂,所以一次http协议无法获取完整的网页,而http是基于tcp通信的,多次http请求就代表这多次tcp的连接,这样的做法势必会导致网页加载速度的下降,由此http/1.1默认开启长连接,只有一个网页的资源请求完成,tcp连接才会关闭。关于长连接的深入学习,具体实现可以阅读这篇博客
cookie + session
http有一个特性:无状态,即无法进行状态的保持,每一次请求都是独立的。但在网页端浏览b站时,登录账号过后,每次访问b站都会保持你的登录信息,其中的原理就与cookie有关

(上图来自网络)当然了,首次登录b站时,你还是需要输入你的账号密码的,一旦选择登录,浏览器就会将你的用户信息通过http协议传输到b站的服务端,服务端认证成功,确认该账号是有效的之后,会生成一个cookie文件,并发送一个set-Cookie的响应,使客户端在磁盘或者内存上保持该cookie文件。之后客户端的http请求就会携带这份cookie文件,服务端收到cookie文件后进行解析,得到有效数据认证成功之后,才会将特定的响应返回给客户端,此时客户端看到的网页就是已经登陆账号的网页了。
如果cookie存储在磁盘上,那么关闭浏览器,甚至关机之后再打开该网页,你的账号登录信息依旧能保持,因为cookie文件在磁盘上,除非你直接删除,否则该文件会一直存在。但是cookie文件存储在内存(浏览器)中时,关闭了浏览器(注意不是关闭网页),浏览器的进程资源被释放,属于浏览器资源的cookie文件当然也被释放,此时再打开浏览器,登录信息就无法保持。如果只是把网站关闭,浏览器没关闭,再打开该网站,登录信息依旧是能保存的,因为cookie文件没有被释放。
但由于安全性的问题,将cookie文件存储在客户端的做法。因为客户端容易遭到攻击,或者说信息容易泄漏,如果cookie被非法窃取,cookie所有者的权益将会受到损害。所以现在主流的策略都是cookie+session,将cookie文件存储在服务端(Linux系统安全性极高)。其主要实现是:客户端提交登录信息,服务端接收后在后台数据库上将这些信息存储起来,然后生成一个唯一的id,这个id可以理解为key,数据库中存储的信息可以理解为value,这就是一对key:value模型。服务端将id返回给客户端,使客户端set-Cookie,将该id值保存起来,此后客户端的http请求都会带上该id值,服务端收到id后,找到其对应value,就能解析出客户的信息,也就能根据这些信息进行会话保持了。
但是cookie+session的方式同样是不安全的,id值同样可以被窃取,被非法利用。但是被窃取的只是一个id值,你的具体信息没有得到泄漏,具体信息存储在服务端的数据库中,要攻击这样的数据库还是比较难的。这也是相对直接使用cookie的优势吧,或者这么说,http协议就是不安全的,它的目的是通信的进行,侧重于通信的实现,至于安不安全就是另外一回事了,因此不推荐用http进行私密数据的传输,要进行这样的传输可以使用更侧重安全性的https协议
相关文章:
Linux | 网络通信 | http协议介绍 | cookie策略讲解
文章目录url统一资源定位符http协议介绍GET vs POSThttp状态码http常见headercookie session上篇博客定制了一个协议,该协议用来进行简单的计算,其包含了数据的序列化和反序列化,编码和解码的定制,并且该协议基于TCP通信…...
招投标系统简介 招投标系统源码 java招投标系统 招投标系统功能设计
项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及…...
winapi获取和修改camera raw界面元素数据
camera raw 界面如下: 需求就是根据 windows api 来操作界面右边的色温、色调、曝光等属性,进而对图片进行调色。根据 spy 捕获的窗口信息,理论上是可以拿到并修改值的。 根据 class 可以先拿到窗口句柄: #define CAMERA_RAW_CLA…...
C++问答汇总_2023自用
C是一种通用编程语言,具有高级抽象、强类型和编译性能等特点。C语言具有许多特性,包括面向对象编程、模板、多态、运算符重载等等。它广泛应用于各种领域,如系统软件、嵌入式系统、游戏开发、科学计算等等。 1、C11相对于C98的新特性…...
IDA 实战--(2)熟悉工具
布局介绍 软件启动后会 有几个选项,一般直接选择Go 即可 之后的工作台布局如下 开始分析 分析的第一个,将PE 文件拖入工作区 刚开始接触,我们先保持默认选项,其它选项后面会详细讲解,点击OK 后,等待分析…...
Deep Unsupervised Learning using Nonequilibrium Thermodynamics论文翻译学习
Deep Unsupervised Learning using Nonequilibrium Thermodynamics Author: Jascha Sohl-Dickstein Link: http://proceedings.mlr.press/v37/sohl-dickstein15.pdf Score: ⭐️⭐️⭐️⭐️⭐️ Status: Done Type: Academic Journal 备注: 首篇扩散模型论文 A central prob…...
使用Autoware标定工具包联合标定相机和激光雷达
前面文章介绍了,安装autoware标定工具包、ros驱动usb相机、robosense-16线激光雷达的使用,本文记录使用Autoware标定工具包联合标定相机和激光雷达的过程。1.ros驱动相机,启动相机;启动激光雷达2.联合录制bag包rosbag record -a 参…...
了解线程安全
线程安全是多线程的重点和难点。 线程安全概念 线程安全:在多线程的各种随机调度顺序下,代码没有bug,都能够符合预期的方式来执行,此时认为线程安全 线程不安全:如果在多线程随机调度下代码出现bug,此时…...
【git】git版本控制
目录 1.在合适的位置打开bush,创建仓库 2.检查:跳转到当前文件夹,显示当前文件夹的相对路径 3.初始化 4.创建一个文本文件readme.txt 5.手动向readme文件中添加一些内容 6.把文件添加到暂存区 7.把文件提交到git仓库 8.手动修改readme.txt文件 9.查看当前…...
模电学习7. 三极管特性曲线与静态工作点
模电学习7. 三极管特性曲线与静态工作点一、三极管的伏安特性曲线1. 三极管的伏安特性曲线2. 三极管的静态工作点二、合适的静态工作点选择1. 合适静态工作点条件2. 静态工作点的确定三、使用立创EDA仿真查看静态工作点1. 搭建如下图所示测试电路2. 点击菜单仿真、仿真设置3. 运…...
LeetCode题解:633. 平方数之和,双指针,JavaScript,详细注释
原题链接: https://leetcode.cn/problems/sum-of-square-numbers/ 解题思路: a和b一定是000到c\sqrt cc之间的某个值。将a的初始值设为0。b的初始值设为c\sqrt cc,b必须为整数。a和b向中间逼近,查找满足条件的值。由于a和b是…...
Keil编译头文件iec_std_functions.h错误解决
Keil 编译IEC61131-3库,头文件,大量出现以下错误; cast to type ? is not allowed compiling resource1.c... ..\PLC\rts\matiec\lib\C\iec_std_functions.h(192): error: #119: cast to type "TIME" is not allowed…...
2022 赣育杯 CTF --- Crypto Lost_N wp
文章目录前言题目解题过程解题代码前言 这是去年江西省赛一道有点小坑的密码题,当时没做出来,今天回想起来重新做一下并且记录一下。 题目 Lost_N.py import gmpy2 from Crypto.Util.number import * # part1 flag bSangFor{} d getPrime(435) cou…...
【趋势分析方法三】MATLAB代码实现TFPW-MK检验
目前水文时间序列趋势分析的方法很多,主要分为参数检验和非参数检验两大类: 参数检验中常用的有线性回归法、滑动平均法、累积距平法等非参数检验则主要包括Mann-Kendal(MK)法和 Spearman 秩次相关法等 虽然从理论上讲ÿ…...
一文学会 Spring 整合 MyBatis
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
ElasticSearch - 文档 | 索引文档 | 检索文档 | 创建索引并指明映射
文章目录1. ElasticSearch是面向文档的2. 索引员工文档3. 检索员工文档4. 映射1. ElasticSearch是面向文档的 在应用程序中对象很少只是一个简单的键和值的列表。通常,它们拥有更复杂的数据结构,可能包括日期、地理信息、其他对象或者数组等。 Elastic…...
SQL中的DML、DDL、DCL分别是什么意思
SQL命令的分类 数据定义语言 DDL(DataDefinition Language) 是 SQL 语言集中负责数据结构定义。 DDL 的核心指令是CREATE、ALTER、DROP。 操作的对象包括:库、表、视图、索引等。 如:CREATE TABLE ; ALTER INDEX; DROP VIEW; 数据…...
kubeasz部署k8s高可用集群
前言:如无特殊说明,所有操作都用root账号在所有节点执行。 说明:kubeasz是一款国产开源的k8s部署软件,采用ansible role的部署方式,部署k8s二进制集群。熟悉ansible role的用该软件部署k8s方便快捷。 一、机器 deplo…...
2022年工程机械出口专题研究【重工】
文章目录2022年工程机械出口专题研究1、中国是全球工程机械第一大市场,竞争力逐步提升2、工程机械出口高增,市场分布趋于多元,企业营收获益3、海外市场高速增长原因为何?4、海外市场增长动能预测附件:2022年工程机械出…...
[python入门(51)] - python时间日期格式time和datetime
目录 ❤ 预备知识 ❤ UTC time Coordinated Universal Time ❤ epoch time ❤ timestamp(时间戳) ❤ stamptime时间戳 ❤ struct_time时间元组 ❤ format time 格式化时间 ❤ time模块编辑 ❤ 获取当前时间的方法 ❤ 当传入默认参…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
git: early EOF
macOS报错: Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...
热烈祝贺埃文科技正式加入可信数据空间发展联盟
2025年4月29日,在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上,可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞,强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...
ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...
