【计算机网络】http协议
目录
前言
认识URL
URLEncode和URLDecode
http协议格式
http方法
GET
POST
GET与POST的区别
http状态码
http常见header
简易的http服务器
前言
我们在序列化和反序列化这一章中,实现了一个网络版的计算器。这个里面设计到了对协议的分析与处理。比如我们应该以约定好的格式发送,然后对方再以特定的方式解析数据。这种双方约定好的格式叫做协议。而实现加减乘除计算的那些逻辑代码,正是我们所说的业务。
我们也发现了制定协议,然后解析协议这些步骤的繁琐。所以已经有大佬帮我们制定好现成的协议了,可以供我们使用和参考。那么http协议顾名思义,也就是对数据的一种解析工作。
认识URL
我们平常所说的“网址”,其实就是url.
URL 是 Uniform Resource Locator 的缩写,中文称为统一资源定位符,它是互联网上标识和定位资源(如网页、图片、视频等)的字符串。URL 用于指定一个资源在互联网上的位置,使用户可以通过浏览器或其他网络工具来访问这个资源。
也就是说,在全球范围内,只要找到它的url就能访问该资源,一个url的组成如下:
协议(Protocol):指定访问资源所使用的协议,如 HTTP、HTTPS、FTP 等。协议通常用于指定客户端与服务器之间的通信规则和方式。
主机名(Host):指定存储资源的计算机的域名或 IP 地址。例如,www.example.com 或 192.168.0.1。其中域名需要解析成先解析成ip地址。域名解析过程需要通过域名系统(DNS)进行,将域名转换为对应的 IP 地址,而 IP 地址可以直接用于网络通信。
端口号(Port):可选项,指定用于访问资源的端口号。如果未指定,默认使用资源所属协议的默认端口。例如,HTTP 默认使用端口号 80,HTTPS 默认使用端口号 443。
路径(Path):指定服务器上资源的路径,用斜杠 “/” 分隔。路径可以是文件的路径或目录的路径。
查询参数(Query Parameters):可选项,提供额外的参数传递给服务器。查询参数以问号 “?” 开头,多个参数之间使用 “&” 分隔。例如,?key1=value1&key2=value2。
片段标识(Fragment Identifier):可选项,用于指定资源中的特定片段。片段标识以井号 “#” 开头,常用于在网页中定位特定的位置。
例如,我们在网站上搜索魔方,然后随便找一张照片,观察此时的地址:
https://baike.baidu.com/pic/%E9%AD%94%E6%96%B9/5275/0/4610b912c8fcc3cec3fdbc20e30cc188d43f87948ac5?fr=lemma&fromModule=lemma_content-image&ct=single#aid=0&pic=4610b912c8fcc3cec3fdbc20e30cc188d43f87948ac5
1.协议:可以看到采用的是https协议,具体后面会细讲.
2.主机名:baike.baidu.com,没有指定端口,则默认指定端口为443.
3.路径:剩下的就都是路径了,其中也包括一些参数等。
也就是说一个url格式如下:
协议://server ip:[port] /a/b/c/d
其中server ip来标识唯一的一台机器,port标识该机器上服务的进程,后面/a/b/c/d代表用户想要的文件名。
URLEncode和URLDecode
URLEncode 和 URLDecode 是用于对 URL 中特殊字符进行编码和解码的过程.
URLEncode
URLEncode 是将 URL 中的特殊字符转换为特殊编码表示的过程。在 URL 中,某些字符具有特殊的含义或用途(例如用于分隔协议、主机名、路径等),如果 URL 中包含这些特殊字符,就需要将其进行编码以确保 URL 的正确解析和传输。
编码规则如下:将需要转码的字符转为两位16进制,前面加上%,编码成%XY格式
例如,字符‘+’的ASCII码值是43,现将其转为16进制,为2B,然后我们再它的前面加上%,成为%2B.例如,我们在网站中输入c++:
还有空格被转化为“%20”等等,都是按这种规则转化的.
URLDecode
URLDecode 是将 URL 中的特殊编码表示转换为原始字符的过程。当服务器接收到一个 URL 时,如果其中包含编码字符,就需要对这些编码字符进行解码以恢复原始的字符表示。URLDecode 通过将特殊编码表示转换为相应的原始字符来实现。例如,将“%2B”解码为‘+’,“%20” 解码为空格。
http协议格式
http请求和响应的报文格式
单纯的站在请求和响应的报文角度,http是基于行的文本协议.
http请求报头格式:
<方法>
:HTTP 请求方法,如 GET、POST、PUT、DELETE 等。<url>
:请求的绝对或相对 URL。<HTTP Version>
:HTTP 协议版本,如 HTTP/1.1、HTTP/2.0。<Header Key>
:报头字段的名称。<Header Value>
:报头字段的值。(<Request Body>)
:可选项,请求正文的内容。
响应的报文格式
<HTTP Version>
:HTTP 协议版本,如 HTTP/1.1、HTTP/2.0。<Status Code>
:请求处理的状态码,如 200(成功)、404(未找到)、500(服务器错误)等。<Reason Phrase>
:状态码对应的简短说明。<Header Key>
:报头字段的名称。<Header Value>
:报头字段的值。(<Response Body>)
:可选项,响应正文的内容。、
首行: [版本号] + [状态码] + [状态码解释]
Header(响应报头): 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度; 如果服务器返回了一个html页面, 那么html页面内容就是在body中.
http方法
我们平时上网的这种行为,其实就两种:
- 1.从服务器中拿下来资源
- 2.将客户端数据上传到服务器
这里是所有方法的汇总:
不同的行为有不同的方法。这里主要有两种GET和POST.
GET
GET通过url传参,即会把获取到的数据回显到url上.
我们从网站上获得、请求到的各种资源,大多是GET方法。例如我们想获取百度首页,我们先telnet连接到百度,然后GET:
- GET用于从服务器获取(或检索)资源,通过URL查询字符串传递参数。
- GET请求可以通过在URL中附加参数来传递数据,这些参数以键值对的形式出现,并使用"?“来将URL路径与参数分隔,不同参数之间使用”&"进行分隔。例如(https://blog.csdn.net/weixin_47257473/article/details/132575491?spm=1001.2014.3001.5501会将参数"spm=1001.2014.3001.5501" 传递给/132575491)
- GET请求的参数会显示在URL中,因此对于敏感数据不宜使用GET请求。GET请求通常用于读取数据,如获取网页内容、检索资源等。
- GET请求是幂等的,即多次执行相同的GET请求,服务器的状态和资源都不应该发生变化。(常见的就是我们点击某个按钮没反应,然后我们就点击多次,但最后就只执行了一次。比如登录的时候,点击多次登录按钮,但最后并不会登录多个qq号).
POST
post是通过正文传参,因此url上不会有相关的数据。
- POST用于向服务器提交(或发送)数据,通过请求体(Request Body)传递参数。
- POST请求的参数通过请求头的Content-Type字段和请求体发送,参数不会显示在URL中,并且可以传输更大量的数据。
- POST请求不会在浏览器的历史记录中留下记录,对于敏感数据和数据的修改操作,应该使用POST请求。
- POST请求是非幂等的,即多次执行相同的POST请求,会对服务器的状态和资源进行修改。
GET与POST的区别
GET和POST本质是没有区别的.使用GET的场景可以使用用POST, POST的场景也可以使用GET。
但是在一些细微的地方还是有一些区别:
- GET是通过把客户端的数据通过请求行(query)来传输到服务端,POST会将客户端数据放入到正文部分然后传输。
- GET 习惯上用于客户端从服务器获取数据,而由于是通过query传输数据,所以是明文的;POST 习惯上是客户端向服务器提交数据,是通过正文部分传输,所以不会显示在上方url中.
- GET的请求是幂等的,而POST的请求可以不是幂等的.
- GET 请求可以被缓存,可以被浏览器保存到收藏夹中;POST 请求不能被缓存.
POST从客户端提交表单给服务器,然后服务器返回给客户端结果.
客户端发送GET请求到服务器,服务器把请求的资源同样返回给客户端.
同样有一点需要说明的是,POST并不比GET安全,因为它们的数据都是明文的,没有加密的。GET只不过是把结果显示到了url中,POST的虽然在正文中没有显示出来,但同样可以获取到正文的数据。
黑客们完全可以在转发的网络节点劫取http请求,然后获得其中的数据,造成我们私密信息的泄露。
http状态码
HTTP状态码是服务器在处理客户端请求时返回的3位数字代码,用于表示请求的处理结果的标准化表示方式。状态码提供了关于请求是否成功、发生了什么错误以及如何处理请求的信息,方便客户端和服务器之间进行通信和理解。
比如我们常见的是404 Not Found.表示服务器没有你请求的资源。
下面是常见的状态码:
1xx:信息性状态码
表示请求已经被接收或正在处理,需要进一步操作或等待,常见的状态码有:
- 100 Continue:接收到请求的初始部分,客户端应继续发送剩余部分。
- 101 Switching Protocols:请求者要求服务器切换协议。
2xx:成功状态码
表示请求已成功处理和接受,常见的状态码有:
- 200 OK:请求成功,返回响应正常。
- 201 Created:请求成功并创建了新的资源。
- 204 No Content:请求成功,但响应没有任何内容。
3xx:重定向状态码
表示请求需要进一步操作以完成请求,常见的状态码有:
- 301 Moved Permanently:请求的资源已永久移动到新位置。
- 302 Found:请求的资源临时移动到其他位置。
- 304 Not Modified:客户端可以使用缓存的版本。
4xx:客户端错误状态码
表示由于客户端的错误或无效请求导致服务器无法处理请求,常见的状态码有:
- 400 Bad Request:请求无效,服务器无法理解。
- 401 Unauthorized:请求需要身份验证。
- 404 Not Found:请求的资源不存在。
5xx:服务器错误状态码
表示由于服务器内部错误导致无法完成请求,常见的状态码有:
- 500 Internal Server Error:服务器遇到了意外的错误,无法完成请求。
- 503 Service Unavailable:服务器当前无法处理请求,通常是由于过载或维护。
总结一张表如下:
http常见header
我们先开启我们的服务端,然后从浏览器中请求服务端,我们看收到的客户端请求:
我们可以看到有很多以冒号分割的(key-value)键值对;每组属性之间使用\n分隔;遇到空行结束。
这些便是header上面http协议格式中也提到了。
- Content-Type: 数据类型(text/html等,例如选择text,浏览器则不会解释html语言,而是直接以文本形式显示.)
- Content-Length: Body的长度
- Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;
- User-Agent: 声明用户的操作系统和浏览器版本信息;
- referer: 当前页面是从哪个页面跳转过来的;
- location: 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问;
- Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能;
我们这里在详细说一下cookie.
我们要知道http特征是:
1.简单快速
2.无连接(连接工作TCP通过三次握手已经帮我们完成了).
3.无状态(即浏览器不知道你是否访问过此界面,但实际我们使用的时候,一般网站会记录我的状态的)
针对于第3点,例如我们需要登录账号才能访问服务。我这次登录后,由于网站没有状态,所以每次进该网站都要登录,会非常的麻烦。所以便有了cookie文件.cookie文件保存了此次用户输入的账号和密码等信息,当用户再次访问该网站时,cookie会自动携带用户的账户和密码发送给服务端,便省去了每次都要登录的步骤。
但是如果有黑客在我们电脑的浏览器中注入了一个木马,然后获取到了我们的cookie信息,这样也就把我们的账号和密码就全部获取到了,这是非常危险的。所以为了避免这些,我们在输入用户名和密码的基础上,加上了认证这一步骤。
当我们从客户端输入账号和密码后,服务器端会利用算法生成一个唯一id -- session id,然后把你的账号和密码全部维护在服务器端,然后把这个session id返回给客户端,此时cookie文件中不再保存账号和密码,而是直接保存这个session id,所以后面再访问服务时不再传输账号和密码,而是直接传输这个session id.
这样就极大程度的保护了用户的个人信息,虽然说黑客还是有一定可能通过这个登录我们的账号,但是我们的个人信息被保护了起来,没有被泄露。而且对应网站也可以采取一些措施,比如如果位置变化很远,服务端便立马让此cookie失效,需要重新输入账号密码。极大程度的保护了我们的隐私安全。
这里便是http协议的全部内容了。
简易的http服务器
这个我们将制作一个简易版的http的demo。我们的目的是当有客户端请求我们的网站时,我们能对这个请求做出响应,并展示请求的结果。
这里我们主要编写服务端,客户端我们使用telnet或者直接网页输入地址进行连接访问即可。
这里共有5个文件,包括Sock.hpp(对socket系列接口的封装)、HttpServer.hpp(服务器的相关接口,主要是包括对服务器的初始化,以及启动等相关操作)、HttpServer.cc(服务器的主逻辑,调用相关接口初始化服务器,并提供一个回调函数即对请求的处理方法HandlerHttpRequest)、Util.hpp(用于对客户端请求字段的切分,服务端提取相关的字段进行处理)、log.hpp(日志文件,只要用于记录相关接口是否被成功调用)。
Sock.hpp
Sock.hpp
这部分前面好几章都已经详细介绍了,代码不变,主要就是对一些接口的封装:
#pragma once #include <iostream> #include <stdlib.h> #include <assert.h> #include <unistd.h> #include <string.h> #include <memory> #include <pthread.h> #include <signal.h> #include <cstring> #include <ctype.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include "log.hpp"using namespace std; class Sock { public:const static int gbacklog = 20;Sock(){}int Socket(){// 1.创建套接字int listensock = socket(AF_INET, SOCK_STREAM, 0);if (listensock < 0){logMessage(FATAL, "%d:%s", errno, strerror(errno));exit(2);}return listensock;}int Bind(int sock, uint16_t port, string ip = "0.0.0.0"){// 2.bindstruct sockaddr_in local;memset(&local, 0, sizeof local);local.sin_family = AF_INET;//使用的协议簇为IPv4local.sin_port = htons(port);//填入端口号//local.sin_addr.s_addr = ip.empty() ? INADDR_ANY : inet_addr(ip.c_str());local.sin_addr.s_addr = INADDR_ANY;if (bind(sock, (struct sockaddr *)&local, sizeof local) < 0){logMessage(FATAL, "bind error", errno, strerror(errno));exit(3);}}void Listen(int sock){// 3.因为TCP是面向连接的,意味着当我们正式通信的时候,需要先建立连接if (listen(sock, gbacklog) < 0){logMessage(FATAL, "listen error", errno, strerror(errno));exit(3);}}// const string& 输入型参数// string* 输出型参数// string& 输入输出型参数int Accept(int listensock, string *ip, uint16_t *port){struct sockaddr_in src;socklen_t len = sizeof src;int servicesock = accept(listensock, (struct sockaddr *)&src, &len);if (servicesock < 0){logMessage(ERROR, "accept error", errno, strerror(errno));return -1;}if (port)*port = ntohs(src.sin_port);if (ip)*ip = inet_ntoa(src.sin_addr);return servicesock;}bool Conncect(int sock,string server_ip, uint16_t server_port){struct sockaddr_in server;memset(&server,0,sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(server_port);server.sin_addr.s_addr=inet_addr(server_ip.c_str());// cout << server.sin_port << " " << server.sin_addr.s_addr << endl;if(connect(sock,(struct sockaddr*)&server,sizeof server) == 0) return true;else {perror("connect"); return false; }}~Sock(){}};
HttpServer.hpp
该服务器类有四个成员变量,分别是listensock_,表示监听的套接字;port_,表示该服务器开放的端口号;Sock类的sock_,用于后续调用相关的socket的接口;func_,表示调用的方法。
#pragma once #include <iostream> #include <unistd.h> #include <signal.h> #include <functional> #include <sys/types.h> #include <string> #include "Sock.hpp"class HttpServer { public:using func_t = function<void(int)>; private:int listensock_;//监听的套接字uint16_t port_;//端口号Sock sock;func_t func_; public:HttpServer(const uint16_t& port,func_t func):port_(port),func_(func){ listensock_ = sock.Socket();sock.Bind(listensock_,port_);sock.Listen(listensock_);}void Start(){for(;;){signal(SIGCHLD,SIG_IGN);string clientIp;uint16_t clientPort;int sockfd = sock.Accept(listensock_,&clientIp,&clientPort);cout << sockfd << endl;if(sockfd < 0){cout << "Accept Error" << endl;continue;}if(fork() == 0){func_(sockfd);exit(1);}close(sockfd);}}~HttpServer(){if(listensock_ >= 0){close(listensock_);}} };
HttpServer.cc
main函数主要是初始化和启动服务器。
然后我们使用的方法是HandlerHttpRequest,该函数如下实现:
先将客户端的请求数据读取到自定义的缓冲,然后对请求到的数据进行切分。
首先由于http协议格式是基于行的文本协议,所以我们可以先按行切分成每段,存放到vector中,然后对第一行进行按空格解析,第一行是 方法 url 协议版本.
我们接下来要对解析出来的url进行分析。我们要知道,根目录在url地址中默认不显示。当我们访问一个网站时,实则是访问的是根目录,默认访问的是根目录中的index.html。
假设我们创建一个根目录是wwwroot,然后在里面再创建一个子目录a,再在a目录中创建一个test.html。这样假设我们要访问test.html时,需要在端口号后面加上/a/index.html.
然后我们构建一个string 响应,先在开头加上"HTTP/1.1 200 OK\r\n" 表示访问成功,然后加上刚才文件的路径,构成一个完整的响应然后send发送给客户端。
代码如下:
#include <iostream> #include <stdio.h> #include <memory> #include <fstream> #include <assert.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "HttpServer.hpp" #include "Util.hpp"// 一般http都有要自己的web根目录 #define ROOT "./wwwroot" // 如果客户端只请求了一个/,我们默认返回首页 #define HOMEPAGE "index.html" using namespace std;void Usage(string proc) {cout << "\nUsage: "<< " port\n"<< endl; } void HandlerHttpRequest(int sockfd) {// 1. 读取请求 for testchar buffer[10240];ssize_t s = recv(sockfd, buffer, sizeof(buffer) - 1, 0);if (s > 0){buffer[s] = 0;}std::cout << buffer << "\n--------------------\n" << std::endl;std::vector<std::string> vline;Util::cutString(buffer, "\n", &vline);std::vector<std::string> vblock;Util::cutString(vline[0], " ", &vblock);std::string file = vblock[1]; std::string target = ROOT;if(file == "/") file = "/index.html";// wwwroot/index.htmltarget += file;std::cout << target << std::endl;std::string content;std::ifstream in(target);if(in.is_open()){std::string line;while(std::getline(in, line)){content += line;}in.close();}std::string HttpResponse;HttpResponse = "HTTP/1.1 200 OK\r\n";HttpResponse += "\r\n";HttpResponse += content;// 2. 试着构建一个http的响应send(sockfd, HttpResponse.c_str(), HttpResponse.size(), 0); }int main(int argc, char *argv[]) {if (argc != 2){Usage(argv[0]);exit(0);}std::unique_ptr<HttpServer> httpserver(new HttpServer(atoi(argv[1]), HandlerHttpRequest));httpserver->Start();return 0; }
Util.hpp
这个文件作用主要是对字符串 按照 指定的字符进行划分。
首先使用find函数,查找指定的字符,得到该字符的下标,然后利用substr得到这一段字符串,然后后面循环如此进行,便把字符串按照指定的字符分隔开了。
#pragma once#include <iostream> #include <vector> #include <string>class Util { public:// aaaa\r\nbbbbb\r\nccc\r\n\r\nstatic void cutString(std::string s, const std::string &sep, std::vector<std::string> *out){std::size_t start = 0;while (start < s.size()){auto pos = s.find(sep, start);if (pos == std::string::npos) break;std::string sub = s.substr(start, pos - start);// std::cout << "----" << sub << std::endl;out->push_back(sub);start += sub.size();start += sep.size();}if(start < s.size()) out->push_back(s.substr(start));} };
还有最后一个日志log.hpp,这个写不写无所谓了,大家可以把上面有关logMessage的去掉即可,或改成if判断也可。
最终效果,我们运行起服务器:
然后我们利用网页访问8081这个端口:
便可以看到已经请求到了,我们看看服务端,客户端发送的请求:
或者我们可以访问指定路径下的资源:
这样便完成了一个简单版的http服务器的编写了。
相关文章:
![](https://img-blog.csdnimg.cn/0aab773f8cfd4bfa9f3e6a2be4cde27a.png)
【计算机网络】http协议
目录 前言 认识URL URLEncode和URLDecode http协议格式 http方法 GET POST GET与POST的区别 http状态码 http常见header 简易的http服务器 前言 我们在序列化和反序列化这一章中,实现了一个网络版的计算器。这个里面设计到了对协议的分析与处…...
![](https://www.ngui.cc/images/no-images.jpg)
仓库太大,clone 后,git pull 老分支成功,最新分支失败
由于 git 仓库太大,新加入的小伙伴在拉取时,无法切换到最新的分支,报错如下: fetch-pack: unexpected disconnect while reading sideband packet fatal: early EOF fatal: fetch-pack: invalid index-pack output在此记录解决步…...
![](https://www.ngui.cc/images/no-images.jpg)
javafx Dialog无法关闭
// 生成二维码图片String qrCodeText "https://example.com";DialogPane grid new DialogPane();grid.setPadding(new Insets(5));VBox vBox new VBox();vBox.setAlignment(Pos.CENTER);Image qrCodeImage generateQRCodeImage(qrCodeText);ImageView customImag…...
![](https://img-blog.csdnimg.cn/c2dcee5eda92455699338f97ca5d9fb8.png)
vue3中TCplayer应用
环境win10:vitevue3elementUI 1 安装 npm install tcplayer.js2 使用 <template><div><video id"player-container-id" width"414" height"270" preload"auto" playsinline webkit-playsinline></video>&l…...
![](https://img-blog.csdnimg.cn/9820a0308eb74dcfaaa842084dbbc7ec.png)
算法通关村14关 | 数据流中位数问题
1. 数据流中位数问题 题目 LeetCode295: 中位数是有序列表中间的数,如果列表长度是偶数,中位数是中间两个数的平均值, 例如:[2,3,4]的中位数是3, [2,3]中位数是(23)/ 2 2.5 设计一个数据结构: …...
![](https://www.ngui.cc/images/no-images.jpg)
工厂模式 与 抽象工厂模式 的区别
工厂模式: // 抽象产品接口 interface Product {void showInfo(); }// 具体产品A class ConcreteProductA implements Product {Overridepublic void showInfo() {System.out.println("This is Product A");} }// 具体产品B class ConcreteProductB impl…...
![](https://img-blog.csdnimg.cn/cc16d5fd094d460aa3a0d271ed5d8e5a.png)
安装虚拟机+安装/删除镜像
安装虚拟机 注意,官网可能无法登录,导致无法从官网下载,就自己去网上搜靠谱的下载,我用的16.2.3 删除镜像 Vm虚拟机怎么删除已经创建的系统?Vm虚拟机创建好之后iso删除方法 - 系统之家 (xitongzhijia.net) 安装镜像…...
![](https://img-blog.csdnimg.cn/img_convert/861f6d487b3170d76ff619b9684813df.png)
MySQL的内置函数复合查询内外连接
文章目录 内置函数时间函数字符串函数数学函数其他函数 复合查询多表笛卡尔积自连接在where中使用子查询多列子查询在from中使用子查询 内连接外连接左外连接右外连接 内置函数 时间函数 函数描述current_date()当前日期current_time()当前时间current_timestamp()当前时间戳…...
![](https://img-blog.csdnimg.cn/img_convert/f7d8aec002d78841f72e60c951609f1c.png)
操作系统(OS)与系统进程
操作系统(OS)与系统进程 冯诺依曼体系结构操作系统(Operator System)进程基本概念进程的描述(PCB)查看进程通过系统调用获取进程标示符(PID)通过系统调用创建进程(fork)进程状态&…...
![](https://www.ngui.cc/images/no-images.jpg)
防重复提交:自定义注解 + 拦截器(HandlerInterceptor)
防重复提交:自定义注解 拦截器(HandlerInterceptor) 一、思路: 1、首先自定义注解; 2、创建拦截器实现类(自定义类名称),拦截器(HandlerInterceptor); 3…...
![](https://img-blog.csdnimg.cn/e81b6c864634479db0445c205ad7abe0.png)
Excel中将文本格式的数值转换为数字
在使用excel时,有时需要对数字列进行各种计算,比如求平均值,我们都知道应该使用AVERAGE()函数,但是很多时候结果却“不尽如人意”。 1 问题: 使用AVERAGE函数: 结果: 可以看到单元格左上角有个…...
![](https://img-blog.csdnimg.cn/5d3e953c079e4ba3a11cb6d1f64f4b73.png)
uni-app开发小程序中遇到的map地图的点聚合以及polygon划分区域问题
写一篇文章来记录以下我在开发小程序地图过程中遇到的两个小坑吧,一个是点聚合,用的是joinCluster这个指令,另一个是polygon在地图上划分多边形的问题: 1.首先说一下点聚合问题,由于之前没有做过小程序地图问题&#…...
![](https://img-blog.csdnimg.cn/a1e9fbce740a484a928cf627c7823c1e.png)
【笔记】软件测试的艺术
软件测试的心理学和经济学 测试是为发现错误而执行程序的过程,所以它是一个破坏性的过程,测试是一个“施虐”的过程。 软件测试的10大原则 1、测试用例需要对预期输出的结果有明确的定义 做这件事的前提是能够提前知晓需求和效果图,如果不…...
![](https://img-blog.csdnimg.cn/b94ccbe06b3c4c68b14170df34a136ac.png)
配置本地maven
安装maven安装包 修改环境变量 vim ~/.bash_profile export JMETER_HOME/Users/yyyyjinying/apache-jmeter-5.4.1 export GOROOT/usr/local/go export GOPATH/Users/yyyyjinying/demo-file/git/backend/go export GROOVY_HOME/Users/yyyyjinying/sortware/groovy-4.0.14 exp…...
![](https://www.ngui.cc/images/no-images.jpg)
C# 按钮的AcceptButton和CancelButton属性
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System...
![](https://www.ngui.cc/images/no-images.jpg)
SMT贴片制造:专业、现代、智能的未来之选
在现代科技的快速发展下,SMT贴片制造作为电子元器件的核心工艺之一,正以其专业、现代和智能的特点成为未来的首选。 随着电子产品越来越小型化,传统的手工焊接已经无法满足高速、高精度、高稳定性的要求。而SMT贴片制造作为一种先进的表面贴…...
![](https://www.ngui.cc/images/no-images.jpg)
python sqlalchemy db.session 的commit()和colse()对session中的对象的影响
实验一:commit()之后查看stu的属性id,查看db.session是否改变 db_test.route("/db_test",methods["GET"]) def db_test():stuStuTest()stu.stu_age22stu.stu_name"nnannns"stu.stu_class11print("sessio…...
![](https://img-blog.csdnimg.cn/26d8de6a4c2a41ba9c5fc95745013110.png)
python读取图像小工具
一、和图像交互获得图像的坐标和像素值 import cv2 import numpy as np import signal import threading import timeif __name__ __main__:img cv2.imread(XXX,0)#读取图片font_face,font_scale,thicknesscv2.FONT_HERSHEY_SIMPLEX,0.5,1#鼠标交互def mouseHandler(event,x…...
![](https://www.ngui.cc/images/no-images.jpg)
【ES6】JavaScript中Reflect
Reflect是JavaScript中的一个内建对象,它提供了一组方法,用于对对象和函数进行操作和检查。这些方法与内建对象的方法非常相似,但具有更高的灵活性。 以下是Reflect对象的一些常用方法: 1、Reflect.apply(target, thisArgument,…...
![](https://img-blog.csdnimg.cn/d44eaf109ecb4813a60939603b3e3cda.png#pic_center)
Ajax + Promise复习简单小结simple
axios使用 先看看老朋友 axios axios是基于Ajaxpromise封装的 看一下他的简单使用 安装:npm install axios --save 引入:import axios from axios GitHub地址 基本使用 axios({url: http://hmajax.itheima.net/api/province}).then(function (result…...
![](https://img-blog.csdnimg.cn/img_convert/8f661138d6d6c892f4c77d8411e9088d.jpeg)
WebDAV之π-Disk派盘 + 小书匠
小书匠是一款功能丰富,强大的知识管理工具。全平台覆盖,离线数据存储,自定义数据服务器,所见即所得的 markdown 编辑体验。 小书匠提供了多种实用的编辑模式,例如:栏编辑、双栏编辑、三栏编辑、全屏写作、全屏阅读等。并且该软件还提供了许多有用的扩展语法,比如Latex公…...
![](https://img-blog.csdnimg.cn/f1c56affffe943bf8afc02b76d65d34a.png)
LTE ATTACH流程、PDN流程、PGW地址分配介绍
1、S-GW\P-GW选择 MME根据S-GW和P-GW的拓扑信息进行S-GW/P-GW的选择,在S-GW的候选序列和P-GW的候选序列中比较,寻找是否有合一的S-GW/P-GW,并且根据S-GW的优先级和权重信息进行排序,得到S-GW/P-GW的候选组。 2、SGW>PGW连接 PD…...
![](https://img-blog.csdnimg.cn/aa5009838124425798e28e70d2479be9.png)
SQL sever中用户管理
目录 一、用户管理常见方法 二、用户管理方法示例 2.1. 创建登录账户: 2.1.1 检查是否创建账户成功: 2.2. 创建数据库用户: 2.2.1检查用户是否创建成功: 2.3. 授予权限: 2.3.1授予 SELECT、INSERT 和 U…...
![](https://img-blog.csdnimg.cn/0489c77c4fba464ebc9a265ebb592657.png)
linux————pxe网络批量装机
目录 一、概述 什么是pxe pxe组件 二、搭建交互式pxe装机 一、配置基础环境 二、配置vsftpd 三、配置tftp 四、准备pxelinx.0文件、引导文件、内核文件 一、准备pxelinux.0 二、准备引导文件、内核文件 五、配置dhcp 一、安装dhcp 二、配置dhcp 六、创建default文…...
![](https://img-blog.csdnimg.cn/img_convert/dd776401937ecb319097fbff3222adc8.png)
处理时延降低24倍,联通云粒数据引擎优化实践
*作者:郑扬勇,云粒星河数据中台产品负责人 云粒智慧科技有限公司成立于 2018 年 6 月,是中国联通集团混改以来成立的首家合资公司,是中国智慧城市数智化建设者。一直以来,云粒智慧以数字化、智能化、集约化产品为核心&…...
![](https://img-blog.csdnimg.cn/441f762d07a448c6a37155ba63aeae01.png)
学习MATLAB
今日,在大学慕课上找了一门关于MATLAB学习的网课,MATLAB对于我们这种自动化的学生应该是很重要的,之前也是在大三的寒假做自控的课程设计时候用到过,画一些奈奎斯特图,根轨迹图以及伯德图,但那之后也就没怎…...
![](https://img-blog.csdnimg.cn/a8141aa122c949f39bf22ea8184d04fa.png#pic_center)
React 18 对 state 进行保留和重置
参考文章 对 state 进行保留和重置 各个组件的 state 是各自独立的。根据组件在 UI 树中的位置,React 可以跟踪哪些 state 属于哪个组件。可以控制在重新渲染过程中何时对 state 进行保留和重置。 UI 树 浏览器使用许多树形结构来为 UI 建立模型。DOM 用于表示 …...
![](https://img-blog.csdnimg.cn/2d63a4ab49b04f67842937dd8ac721f0.png)
MySQL之事务与引擎
目录 一、事物 1、事务的概念 2、事务的ACID特点 3、事务之间的相互影响 4、Mysql及事务隔离级别(四种) 1、查询会话事务隔离级别 2、查询会话事务隔离级别 3、设置全局事务隔离级别 4、设置会话事务隔离级别 5、事务控制语句 6、演示 1、测试提交事务 2、测试事务回滚 4…...
![](https://www.ngui.cc/images/no-images.jpg)
Flink集群常见的监控指标
为确保能够全面、实时地监控Flink集群的运行状态和性能指标。以下是监控方案的主要组成部分: Flink集群概览:通过访问Flink的JobManager页面,您可以获取集群的总体信息,包括TaskManager的数量、任务槽位数量、运行中的作业以及已…...
![](https://www.ngui.cc/images/no-images.jpg)
React常见知识点
1. setCount(10)与setCount(preCount > preCount 10) 的区别: import React, { useState } from react; export default function CounterHook() {const [count, setCount] useState(() > 10);console.log(CounterHook渲染);function handleBtnClick() {//…...
![](/images/no-images.jpg)
java web网站开发项目/2022最新永久地域网名
1、sleep()和wait() wait()放弃对象锁,只有对此对象发出notify()方法,才能使其进入线程池。 2、final、fially、finalize的区别 3、&:是位操作符。 &…...
![](http://www.d1net.com/uploadfile/2017/0609/20170609044850334.jpg)
免费企业网络推广网站/恶意点击软件哪个好
根据调研机构Semicast Research最新报告,2016年全球工业半导体市场规模为422亿美元,较2015年407亿美元,成长3.7%。主要成长动能仍然依靠于传统模拟IC、光电元件,以及功率元件等产品。 工业半导体泛指供应工业部门各项设备、应用与…...
![](/images/no-images.jpg)
网站友情链接模板/在线生成网页网站
Web端自动化元素定位方法 随着互联网的快速发展,版本迭代周期越来越短?需求越来越多?测试工作量越来越大?怎么保证质量?怎么保证上线周期?。如何实现既提高测试效率和覆盖率,又节约测试成本&…...
![](https://img-blog.csdnimg.cn/2020042217384474.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25ldHdvcmtodW50ZXI=,size_16,color_FFFFFF,t_70)
wordpress 最简单皮肤/哪个搜索引擎能搜敏感内容
问题起因 近日做的一个项目,我们提供jar包给其它开发方做开发,用户调用jar包里的一个功能,该功能执行后写了数据库。客户需要在该该功能执行完后能得到通知,这客户可以去数据库中取新的刷新后的数据。 什么是回调 java中一个类&…...
![](https://img-blog.csdnimg.cn/img_convert/1b985bc78b87d861d9fa2538ab110513.png)
wordpress 更改插件目录/成都官网seo费用
摘要移动端应用以及服务端节约空间都需要对当前的大模型进行适当压缩。本文继续介绍一种模型压缩方法。实际除了各种形式的distilling方式,混合精度计算与量化压缩方法也是非常常用的。一、methodology1.1 混合精度实际在TensorFlow矩阵计算中,大多数是使…...
![](https://img-blog.csdnimg.cn/img_convert/ae7ab0b52c87cd9772d808ac1351dc14.png)
设计模板免费网站/怎么开发自己的小程序
前言 上个星期,我分享了一篇关于Android组件化的文章↓↓↓ Android组件化初探【含Demo】 后面看见评价区有朋友就“组件化”这个知识点发表了自己的看法。 我觉得这位朋友说的很有道理,今天在这里就想和大家好好探讨一下“组件化”这个知识点。 为什么…...