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

【网络】http协议

🥁作者华丞臧.
📕​​​​专栏:【网络】
各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞+收藏+关注)。如果有错误的地方,欢迎在评论区指出。
推荐一款刷题网站 👉 LeetCode刷题网站


文章目录

  • 前言
  • 一、http协议
    • 1.1 认识URL
      • http是做什么的
      • urlencode和urldecode
    • 1.2 http格式
      • http请求
      • http响应
    • 1.3 http的方法
    • 1.4 http的状态码
    • 1.5 http常见Header
  • 二、http服务器
    • 2.1 最简单的http服务器
    • 2.2 简单的http服务器
    • 2.3 html的http服务器
    • 2.4 表单
      • get
      • post
      • get和post特点
    • 2.5 永久和临时重定向
    • 2.6 Cookie


前言

在上一篇文章中我们见识了序列化和反序列化,其是处于应用层的,是进行网络通信双方进行一种约定;在网络发展至今,已经有了一些非常成熟的场景,并且有大佬自定义的一些协议,写的很好因此成为了应用层特定协议的标准,

一、http协议

虽然我们说,应用层协议是我们程序猿自己定的。但实际上,已经有大佬们定义了一些现成的,又非常好用的应用层协议,供我们直接参考使用,http(超文本传输协议)就是其中之一,底层主流采用的是tcp协议,http是无连接的。

1.1 认识URL

平时我们所说的网址就是URL。
在这里插入图片描述

服务器地址是域名,域名就是字符串类型的字段,域名在我们访问网网站的时候必须被转换称为IP地址,访问网络服务必须具有网络号即端口号,网络通信的本质就是socket,IP+port。
一般在使用确定协议的时候,再url上面会缺省端口号,在进行网络通信时端口号会被(浏览器)自动添加上,所以浏览器访问指定url时,浏览器必须给我们自动添加port,浏览器就必须知道这些端口,所以特定的众所周知的服务端口号都是并且必须是确定的。因此,在前面学习端口号时,我们说用户自己使用的套接字不能在0~1023。

http --> 80
https --> 443
sshd --> 22

http是做什么的

http是以网页的形式呈现的,比如说查阅文档、查看视频;所以http是获取网页资源的,视频、音频等也都是文件,而网页也是一个.html文件。

http是向特定服务器申请特定资源的,获取到本地进行展示或者某种使用的。

网页上的资源在该网页的网络服务器(软件)所在的服务器(硬件)上,而服务器都是Linux,资源文件存放在Linux服务器上;用户在网页上申请资源时,服务器需要根据路径找到该文件,所以URL中需要添加资源文件的路径。/是Linux下的路径分隔符,但是需要注意这个/不一定为根目录,因为软件层面可以做一些处理,比如在这个目录前添加一个路径。

urlencode和urldecode

像 / ? :等这样的字符,已经被url当做特殊意义理解了,因此这些字符不能随意出现。
比如, 某个参数中需要带有这些特殊字符,就必须先对特殊字符进行转义。在进行网络传输进行编码时,尤其是http中有些字段也会进行编码,服务端进行解码。编码是浏览器做的,解码是服务器做的。
转义的规则如下:
将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。
在这里插入图片描述

“+” 被转义成了 “%2B”
urldecode就是urlencode的逆过程:
urlencode工具

网页的内容在开发者工具中可以看到,如下图:
在这里插入图片描述

1.2 http格式

http是基于行的协议。
在这里插入图片描述

http请求

在这里插入图片描述

  • 首行:[方法] + [url] + [版本]
  • Header:请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束 。
  • Body:空行后面的内容都是Body,Body允许为空字符串。如果Body存在,则在Header中会有一个 Content-Length属性来标识Body的长度。

http响应

在这里插入图片描述

  • 首行: [版本号] + [状态码] + [状态码解释]
  • Header:请求的属性,冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束。
  • Body:空行后面的内容都是Body,Body允许为空字符串。如果Body存在, 则在Header中会有一个 Content-Length属性来标识Body的长度;如果服务器返回了一个html页面,那么html页面内容就是在 body中。

1.3 http的方法

方法说明支持的HTTP协议版本
GET获取资源1.0、1.1
POST传输实体主体1.0、1.1
PUT传输文件1.0、1.1
HEAD获取报文首部1.0、1.1
DELETE删除文件1.0、1.1
OPTIONS询问支持的方法1.1
TRACE追踪路径1.1
CONNECT要求用隧道协议链接代理1.1
LINK建立和资源之间的联系1.0
UNLINE断开连接关系1.0

其中最常用的就是GET方法和POST方法.

1.4 http的状态码

类别原因短语
1XXInformational(信息状态码)接收的请求正在处理
2XXSuccess(成功状态码)请求正常处理完毕
3XXRedirection(重定向状态码)需要进行附加操作以完成请求
4XXClient Error(客户端错误状态码)服务器无法处理请求
5XXServer Error(服务器错误状态码)服务器处理请求出错

最常见的状态码, 比如 200(OK), 404(Not Found), 403(Forbidden), 302(Redirect, 重定向), 504(Bad Gateway)

1.5 http常见Header

  • Content-Type: 数据类型(text/html等)
  • Content-Length: Body的长度
  • Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;
  • User-Agent: 声明用户的操作系统和浏览器版本信息;
  • referer: 当前页面是从哪个页面跳转过来的;
  • location: 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问;
  • Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能;

二、http服务器

2.1 最简单的http服务器

使用tcp协议的服务器端,在浏览器中可以连接该服务器,浏览器上默认使用http协议进行连接。在前几篇文章中已经编写了tcp套接字,这里只需要编写提供服务的代码即可。

#include <iostream>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<sys/types.h>
#include<sys/wait.h>
#include "Log.hpp"using namespace std;
volatile bool quitSer = false;void Usage(void *vgs)
{std::cout << "Usage:./tcpserver port ip" << std::endl;
}
//提供服务
void Serverhttp(int sock)
{char buffer[10240];ssize_t s = read(sock, buffer, sizeof buffer);cout << s << endl;if(s > 0){logMessage(DEBUG, "read success..");std::cout << buffer;}
}class server
{
public:server(int port, std::string ip = ""): sockfd_(-1), ip_(ip), port_(port){}~server(){}public:void init(){// 1. 创建套接字sockfd_ = socket(AF_INET, SOCK_STREAM, 0);if (sockfd_ < 0){logMessage(FATAL, "socket:%s[%d]", strerror(errno), sockfd_);exit(SOCK_ERR);}logMessage(DEBUG, "socket success..");// 2.填充域struct sockaddr_in local;bzero(&local, sizeof(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));// 3. 绑定网络信息if (bind(sockfd_, (const struct sockaddr *)&local, sizeof(local)) < 0){logMessage(FATAL, "bind:%s[%d]", strerror(errno), sockfd_);exit(BIND_ERR);}logMessage(DEBUG, "bind success...");// 4. 监听套接字if (listen(sockfd_, 5) < 0){logMessage(FATAL, "listen:%s[%d]", strerror(errno), sockfd_);exit(LISTEN_ERR);}logMessage(DEBUG, "listen success...");// 完成}void start(){char inbuffer_[1024]; // 用来接收客户端发来的消息// 提供服务while (true){quitSer = false;struct sockaddr_in peer;socklen_t len = sizeof(peer);// 5. 获取连接, accept 的返回值是一个新的socket fdlogMessage(DEBUG,"start1");int serviceSock = accept(sockfd_, (struct sockaddr *)&peer, &len);logMessage(DEBUG,"start2");if (serviceSock < 0){// 获取链接失败logMessage(WARINING, "accept: %s[%d]", strerror(errno), serviceSock);continue;}logMessage(DEBUG, "accept success");pid_t id = fork();if(id == 0){pid_t tid = fork();if(tid == 0){uint16_t peerPort = htons(peer.sin_port);std::string peerIp = inet_ntoa(peer.sin_addr);Serverhttp(serviceSock);exit(0);}exit(0);}close(serviceSock);int ret = waitpid(id, nullptr, 0);if(ret < 0){logMessage(WARINING, "wait child error:%d", errno);}logMessage(DEBUG, "wait success...");}}private:int sockfd_;uint16_t port_;std::string ip_;
};// ./tcpserver port ip
int main(int argc, char *argv[])
{if (argc < 2 || argc > 3){Usage(argv[0]);exit(USAGE_ERR);}uint16_t port = atoi(argv[1]);std::string ip;if (argc == 3)ip = argv[2];std::cout << port << ":" << ip << std::endl; server tcpSer(port, ip);tcpSer.init();tcpSer.start();return 0;
}

服务端并没有提供服务,所以访问服务器时网页显示如下图:
在这里插入图片描述

在Linux服务端可以看到请求的相关属性,如下图:
在这里插入图片描述

2.2 简单的http服务器

服务器收到请求,提供服务向对应的套接字文件中写入一个“hello world”,注意响应的格式为首行+header+body,其中header和body之间需要空一行。

void Serverhttp(int sock)
{char buffer[10240];ssize_t s = read(sock, buffer, sizeof buffer);cout << s << endl;if(s > 0){logMessage(DEBUG, "read success..");std::cout << buffer;}//开始响应string response;response = "HTTP/1.0 200 OK\r\n"; //响应首行response += "\r\n";   //空行response += "hello world!!";  //正文send(sock, response.c_str(), response.size(), 0);
}

服务器收到的请求报文如下图:
在这里插入图片描述
浏览器收到的响应如下图:
在这里插入图片描述
使用telnet可以查看服务器给用户的响应。

//安装telnet
sudo yum install -y telnet//使用格式
telnet ip port
//connected后
//出现escape character时使用ctrl+}
//输入请求

在这里插入图片描述

2.3 html的http服务器

作为服务端,它并不关心html的信息也不需要管html的格式是什么,服务器只负责网络请求并且把网页信息给用户推过去就行了,所以实际上在进行网站开发时,网页的资源都是通过html文件推送给用户的,请求的文件在请求行中,其第二个字段就是用户需要访问的文件,如下图:
在这里插入图片描述
其中/并不是根目录,而是web根目录,可以设置成为根目录。

在这里插入图片描述

//获取资源路径
string getPath(string in)
{size_t pos = in.find(CRLF);string request = in.substr(0, pos);cout << "request:" << request << endl;// get path http/1.0size_t first = request.find(SPACE); //第一个空格cout << "first:" << first << endl;if(first == string:: npos) return nullptr;size_t second = request.rfind(SPACE); //第二个空格cout << "second:" << second << endl;if(second == string::npos) return nullptr;string path = request.substr(first + SPACE_LEN, second- (first + SPACE_LEN));if(path.size() == 1 && path[0] == '/') path += HOME_PAGE; //用户访问根目录,就返回主页cout << "getPath:" << path << endl;return path;
}
//获取资源
string readFile(string& recource)
{ifstream in(recource);if(!in.is_open()) return "404";string content;string line;while(getline(in, line)) content += line;return content;
}//提供服务
void Serverhttp(int sock)
{//std::cout << peerIp << ":" << peerPort << std::endl;char buffer[10240];ssize_t s = read(sock, buffer, sizeof buffer);cout << s << endl;if(s > 0){logMessage(DEBUG, "read success..");std::cout << buffer;}// 1. 获取路径string path = getPath(buffer);string recource = ROOT_PATH;recource += path;cout << recource << endl;// 获取对应文件内容string html = readFile(recource);// 开始响应string response;response = "HTTP/1.0 200 OK\r\n";response += "Content-Type:text/html\r\n";response += ("Content-Length:" + std::to_string(html.size()) + "\r\n");response += "\r\n";//response += "<html><h1>hello world!!</h1><html>\r\n";response += html;send(sock, response.c_str(), response.size(), 0);
}

关于html的编写方法可以参考👉菜鸟教程

//index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"> //
<title>华丞臧(runoob.com)</title> //网页名称
</head>
<body> //正文<h1>我的第一个标题</h1>   //标题<p>我的第一个段落。</p>
</body>
</html>

在浏览器中访问服务器可以看到网页显示如下图所示:

在这里插入图片描述
Liunx上收到的请求如下图,左为服务器收到的请求,右为客户端收到的响应。
在这里插入图片描述

2.4 表单

用户的网络行为无非有两种

  1. 用户将自己的远端资源拿到本地:get /index.html http/1.1;
  2. 用户想将自己的属性字段提交到远端。

在浏览器上,网页通常会让用户注册一个账号,用来标识该用户,用户的存放在远端的资源也可以使用该账号标识,在html中这种端口称为表单。

get

在http中get会以明文方式将用户对应的参数信息拼接到url中。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>华丞臧(runoob.com)</title>
</head>
<body><h1>hello world</h1><p>我的第一个段落。</p><form action="html_form_action.php" method="get">Username: <input type="text" name="user"><br>Password: <input type="password" name="passwd"><br><input type="submit" value="Submit"></form>
</body>
</html>

表单形式如下图所示:
在这里插入图片描述

在这里插入图片描述

post

在http中post会以明文方式将用户对应的参数信息拼接到正文中。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>华丞臧(runoob.com)</title>
</head>
<body><h1>hello world</h1> <p>我的第一个段落。</p><form action="html_form_action.php" method="post">Username: <input type="text" name="user"><br>  //用户名,<br>标识换行Password: <input type="password" name="passwd"><br>  //密码<input type="submit" value="Submit"></form>
</body>
</html>

表单形式如下图所示:
在这里插入图片描述
在表单中填入用户名和密码后,可以看到url中并没有拼接用户参数,如下图:
在这里插入图片描述
使用progress telerik fiddler可以查看用户发送的请求报文(Raw),可以看到用户参数被拼接到正文当中,如下图:
在这里插入图片描述
在服务端也可以收到用户发来的请求,如下图:
在这里插入图片描述

get和post特点

不难发现,不管是get方法还是post方法都是不安全的,都是以明文的方式传输;如果有第三方来攻击用户,无疑能非常简单的获取用户的数据;与get方法相比,post方法只是更为私密但还是明文传输,不过post方法会将参数添加到请求的正文中,因此当用户需要传输大资源的时候无疑使用post方法更加合适。

2.5 永久和临时重定向

301:永久重定向。

void Serverhttp(int sock)
{char buffer[10240];ssize_t s = read(sock, buffer, sizeof buffer);cout << s << endl;if(s > 0){logMessage(DEBUG, "read success..");std::cout << buffer;}string response = "HTTP/1.1 301 Permanent redirect\r\n";   //永久重定向response +="Location: https://blog.csdn.net/qq_59456417?spm=1011.2415.3001.5343r\n";response += "\r\n";send(sock, response.c_str(), response.size(), 0);
}

访问服务器结果如下:
在这里插入图片描述

302:临时重定向。

void Serverhttp(int sock)
{char buffer[10240];ssize_t s = read(sock, buffer, sizeof buffer);cout << s << endl;if(s > 0){logMessage(DEBUG, "read success..");std::cout << buffer;}string response = "HTTP/1.0 302 Temporary redirect\r\n";   //临时重定向response +="Location: https://www.qq.com/r\n";response += "\r\n";send(sock, response.c_str(), response.size(), 0);
}

访问服务器结果如下:
在这里插入图片描述

  • 临时重定向:当客户端发起请求时,服务端对请求不进行处理,但是服务端会给可会端返回一个302状态码,并且在属性字段还会返回一个Location字段,客户端会根据这个字段进行自动跳转;如果服务器只是做一个局部性的临时的升级或者短时间不能使用,这时我们就可以进行临时重定向,如果有用户访问,就将临时重定向到对应的服务器上。。
  • 永久重定向:当客户端发起请求时,服务端对请求不进行处理,但是服务端会给可会端返回一个301状态码,并且在属性字段还会返回一个Location字段,客户端会根据这个字段进行自动跳转;如果服务器永久不再使用,但是该服务器积累了一定的用户,这时我们就可以搞一个同样的服务器进行永久重定向,如果有用户访问,就重定向到对应的服务器上。
  • 临时和永久重定向的区别在于客户端浏览器的处理,对于临时重定向浏览器不会记录重定向的目标位置,对于永久重定向浏览器会记录重定向的目标位置,所以永久重定向访问一次后再次访问时浏览器就会直接访问记录的服务器,注意并不是所有浏览器都会去做将永久重定向的网址更新。
  • 服务器的资源是否愿意被临时访问还是愿意永久访问,决定是临时重定向还是永久重定向。

2.6 Cookie

http状态特点之一:无状态,用户各种资源的请求http协议不会记录,也就是说http不知道用户访问服务器次数;虽然http不会记录,但http可以借助其他的手段来记录用户的访问。

为什么需要记录呢?

因为用户需要会话保持,网站中某些资源是需要进行用户认证的,如果访问不被记录,就会导致每次访问资源都需要进行用户认证,比如在腾讯视频上每次访问vip影视都需要用户进行一次登录这显然是非常麻烦的的,所以服务器需要保持用户会话。

我们可以登录一下bilibili如下所示,点击网址左边的锁,可以看到有一个Cookie,Cookie是一种浏览器会话保持的策略。
在这里插入图片描述

在Cookie类表中可以找到以bilibili开头的:
在这里插入图片描述
当你把Cookie中关于bilibili的全部删除,下一次再进入bilibili时就需要重新登陆了。

Cookie内容:

  • 用户名
  • 密码
  • 到期时间
  • 地址
  • 等等
void Serverhttp(int sock)
{char buffer[10240];ssize_t s = read(sock, buffer, sizeof buffer);cout << s << endl;if(s > 0){logMessage(DEBUG, "read success..");std::cout << buffer;}// 1. 获取路径string path = getPath(buffer);string recource = ROOT_PATH;recource += path;cout << recource << endl;string html = readFile(recource);// 开始响应string response;response = "HTTP/1.0 200 OK\r\n";response += "Content-Type:text/html\r\n";response += ("Content-Length:" + std::to_string(html.size()) + "\r\n");response += "Set-Cookie: this is my Cookie content\r\n";response += "\r\n";response += html;send(sock, response.c_str(), response.size(), 0);
}

在这里插入图片描述
Cookie就是浏览器给用户维护的一个文件,Cookie可以在磁盘上也可以在内存中,内存中的Cookie将浏览器关闭后Cookie就会释放,再次启动浏览器访问服务器时就需要重新登录。Cookie对用户的安全极大的影响,第三方如果拿到用户的Cookie,第三方就可以通过Cookie使用用户的身份登录服务器,更严重的第三方还是以通过Cookie拿到用户的用户名和密码。

Cookie策略存在极大的安全隐患,所以现在主流的方案不是Cookie,而是Cookie + session的方式。服务器将用户名和密码形成一个session文件,这个文件的文件名session_id在服务器上具有唯一性,服务器将session_id返回客户端,客户端将session_id写入本地的Cookie,后续访问都会通过session_id去访问服务器,此时用户的用户名和密码就是存放在服务器上,软件厂商来维护session和cookie,大公司有充足的动力和能力来保护自己不受攻击,并且还会有各种措施来防护。
在这里插入图片描述

补充:

  • http-pipeline:怎么请求的,就按顺序来响应。

相关文章:

【网络】http协议

&#x1f941;作者&#xff1a; 华丞臧. &#x1f4d5;​​​​专栏&#xff1a;【网络】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站 文章…...

Thread::interrupted() 什么意思? 如何中断线程?

1、答&#xff1a; Thread::interrupted() 是一个静态方法&#xff0c;用于判断当前线程是否被中断&#xff0c;并清除中断标志位。 具体来说&#xff0c;当一个线程被中断后&#xff0c;它的中断状态将被设置为 true。如果在接下来的某个时间点内调用了该线程的 interrupted…...

Oracle OCP 19c 考试(1Z0-083)中关于Oracle不完全恢复的考点(文末附录像)

欢迎试看博主的专著《MySQL 8.0运维与优化》 下面是Oracle 19c OCP考试&#xff08;1Z0-083&#xff09;中关于Oracle不完全恢复的题目: A database is configured in ARCHIVELOG mode A full RMAN backup exists but no control file backup to trace has been taken A media…...

一起来学习配置Combo接口吧!

Combo接口是一个光电复用的逻辑接口&#xff0c;一个Combo接口对应设备面板上一个GE电接口和一个GE光接口。电接口与其对应的光接口是光电复用关系&#xff0c;两者不能同时工作&#xff08;当激活其中一个接口时&#xff0c;另一个接口就自动处于禁用状态&#xff09;&#xf…...

C++模拟实现红黑树

目录 介绍----什么是红黑树 甲鱼的臀部----规定 分析思考 绘图解析代码实现 节点部分 插入部分分步解析 ●父亲在祖父的左&#xff0c;叔叔在祖父的右&#xff1a; ●父亲在祖父的右&#xff0c;叔叔在祖父的左&#xff1a; 测试部分 整体代码 介绍----什么是红黑树 红…...

HTTPS协议之SSL/TLS详解(下)

目录 前言&#xff1a; SSL/TLS详解 HTTP协议传输安全性分析 对称加密 非对称加密 证书 小结&#xff1a; 前言&#xff1a; 在网络世界中&#xff0c;存在着运营商劫持和一些黑客的攻击。如果明文传输数据是很危险的操作&#xff0c;因为我们不清楚中间传输过程中就被哪…...

OLE对象是什么?为什么要在CAD图形中插入OLE对象?

OLE对象是什么&#xff1f;OLE对象的意思是指对象连接与嵌入。那为什么要在CAD图形中插入OLE对象&#xff1f;一般情况下&#xff0c;在CAD图形中插入OLE对象&#xff0c;是为了将不同应用程序的数据合并到一个文档中。本节内容小编就来给大家分享一下在CAD图形中插入OLE对象的…...

【微信小程序】-- 自定义组件 -- 数据、方法和属性(三十三)

&#x1f48c; 所属专栏&#xff1a;【微信小程序开发教程】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &…...

【Spring 深入学习】AOP的前世今生之代理模式

AOP的前世今生之代理模式1. 概述 什么是代理模式呢&#xff1f;&#xff1f;&#xff1f; 在不修改原有代码 或是 无法修改原有代码的情况下&#xff0c;增强对象功能&#xff0c;替代原来的对象去完成功能&#xff0c;从而达成了拓展的目的。 先给大家看下 JavaScript中实现方…...

操作系统复试

2017软学 给出操作系统的定义&#xff0c;分别从资源管理&#xff0c;任务调度&#xff0c;用户接口等三个方面论述操作系统的职能 操作系统是位于硬件层之上、所有其他系统软件层之下的一个系统软件&#xff0c;使得管理系统中的各种软件和硬件资源得以充分利用&#xff0c;方…...

藏经阁(五)温湿度传感器 SHT3x-DIS 手册 解析

文章目录芯片特性芯片内部框图芯片引脚定义芯片温湿度范围芯片寄存器以及时序讲解信号转换公式芯片特性 湿度和温度传感器完全校准&#xff0c;线性化温度补偿数字输出供电电压范围宽&#xff0c;从2.4 V到5.5 VI2C接口通讯速度可达1MHz和两个用户可选地址典型精度 2% RH和 0.…...

PCB焊盘设计基本原则

SMT的组装质量与PCB焊盘设计有直接的关系&#xff0c;焊盘的大小比例十分重要。如果PCB焊盘设计正确&#xff0c;贴装时少量的歪斜可以再次回流焊纠正(称为自定位或自校正效应)&#xff0c;相反&#xff0c;如果PCB焊盘设计不正确&#xff0c;即使贴装位置十分准确&#xff0c;…...

mysql锁分类大全

前言 为什么会出现锁 MySQL中的锁是为了保证并发操作的正确性和一致性而存在的。 当多个用户同时对同一份数据进行操作时&#xff0c;如果不加控制地进行读写操作&#xff0c;就可能导致数据不一致的问题。例如&#xff0c;当多个用户同时对同一行数据进行写操作时&#xff…...

推荐几款主流好用的远程终端连接管理软件

一、介绍 远程终端连接管理软件是管理服务器、虚拟机等远程计算机系统不可或缺的工具之一&#xff0c;它可以通过网络连接到另一台计算机&#xff0c;以执行命令、编辑文件或进行其他管理任务&#xff0c;下面我将为大家介绍几款主流好用的远程终端连接管理软件&#xff0c;并…...

描述性统计

参考文献 威廉 M 门登霍尔 《统计学》 文章目录定性数据的描述方法条形图饼图帕累托图定量数据点图茎叶图频数分布直方图MINITAB 工具在威廉《统计学》一书将统计学分为描述统计学和推断统计学&#xff0c;他们的定义分别如下&#xff1a;描述统计学&#xff1a;致力于数据集的…...

第十四届蓝桥杯三月真题刷题训练——第 7 天

目录 第 1 题&#xff1a;三角回文数 问题描述 答案提交 运行限制 代码&#xff1a; 第 2 题&#xff1a;数数 问题描述 答案提交 运行限制 代码&#xff1a; 第 3 题&#xff1a;倍数问题_同余定理_分情况讨论 题目描述 输入描述 输出描述 输入输出样例 运行限…...

剑指 Offer 57. 和为s的两个数字

一、题目 输入一个递增排序的数组和一个数字s&#xff0c;在数组中查找两个数&#xff0c;使得它们的和正好是s。如果有多对数字的和等于s&#xff0c;则输出任意一对即可。 示例 1&#xff1a; 输入&#xff1a;nums [2,7,11,15], target 9 输出&#xff1a;[2,7] 或者 [7…...

PDF转word在线转换方法!操作简单又高效

相信很多已经工作的人都知道&#xff0c;PDF文件格式的优点在于兼容性强、安全性高&#xff0c;而且查看和传输给他人都很方便。但是&#xff0c;这种格式的文件也有不太方便的地方&#xff0c;那就是不能对文件内容进行编辑和修改。对于许多人来说&#xff0c;如果想要编辑修改…...

Jquery项目中使用vue.js

大家在工作的情况中&#xff0c;可能会遇到之前的老项目采用jq书写&#xff0c;或者修改或者新增功能在jq中&#xff0c;原始jq的项目,代码可维护性很差,一个页面几千行jq,可维护性很差,工作量巨大&#xff0c;所以这个时候大家可以引入vue.js。 第一步&#xff1a;引入vue.js…...

蓝桥杯 删除字符

题目描述 给定一个单词&#xff0c;请问在单词中删除 t 个字母后&#xff0c;能得到的字典序最小的单词是什么&#xff1f; 输入描述 输入的第一行包含一个单词&#xff0c;由大写英文字母组成。 第二行包含一个正整数 t。 其中&#xff0c;单词长度不超过 100&#xff0c…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建

【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...

【笔记】AI Agent 项目 SUNA 部署 之 Docker 构建记录

#工作记录 构建过程记录 Microsoft Windows [Version 10.0.27871.1000] (c) Microsoft Corporation. All rights reserved.(suna-py3.12) F:\PythonProjects\suna>python setup.py --admin███████╗██╗ ██╗███╗ ██╗ █████╗ ██╔════╝…...

构建Docker镜像的Dockerfile文件详解

文章目录 前言Dockerfile 案例docker build1. 基本构建2. 指定 Dockerfile 路径3. 设置构建时变量4. 不使用缓存5. 删除中间容器6. 拉取最新基础镜像7. 静默输出完整示例 docker runDockerFile 入门syntax指定构造器FROM基础镜像RUN命令注释COPY复制ENV设置环境变量EXPOSE暴露端…...