【Linux进阶之路】HTTP协议
文章目录
- 一、基本概念
- 1.HTTP
- 2.域名
- 3.默认端口号
- 4.URL
- 二、请求与响应
- 1.抓包工具
- 2.基本框架
- 3.简易实现
- 3.1 HttpServer
- 3.2 HttpRequest
- 3.2.1 version1
- 3.2.2 version2
- 3.2.3 version3
- 总结
- 尾序
一、基本概念
- 常见的应用层协议:
- HTTPS (
H
yperT
extT
ransferP
rotocolS
ecure),安全
的超文本传输数据。- FTP(
F
ileT
ransferP
rotocol) ,网络之间的文件
传输。- SMTP(
S
impleM
ailT
ransferP
rotocol),邮件
传输。- DNS(
D
omainN
ameS
ystem),域名
解析。- SSH(
S
ecureSH
ell),加密的远程登录
会话。
- 一般来讲,大多数情况用现成的应用层协议即可,但是如果做游戏引擎,或者做一些比较私密,对安全性要求很高的项目时,可能需要内部指定自定义协议。
1.HTTP
- HTTP(
H
yperT
extT
ransferP
rotocol)是一种用于传输超文本数据的应用层协议
。 - 应用于Web服务器与Web浏览器之间进行通信。
- 明文传输(可能会暴露个人隐私数据),因此不安全,但是简单易用,被广泛支持。
- 对于HTTP的不安全,之后发展出了HTTPS,即" 安全的HTTP "。
浏览器简介:
- 浏览器简单来看就是处理数据的一种工具,浏览器可以解析一些常用的应用层协议的数据,通过相应的连接方式向服务端发送请求,接收响应并将文件给我们以相应的格式呈现出来,具体如何呈现出一个完美的网页,则是前端开发人员的工作了,接下来的内容我们会制作一个简单的网页 ~
- 市面上的浏览器多种多样,因为掌握了浏览器,也就掌握了进入网络的通道,因此各大公司在早期为了发展,争相竞争推动了浏览器技术的发展,发展出了成熟的浏览器,目前浏览器呈现的一般都是跟搜索引擎相结合的模式,通过搜索网址和关键词,从而使用户进入目标网站。
- 现在由于ChatGpt的出现让信息可以通过对话的形式体现,相比搜索引擎的关键词搜索更加的便利,让我们获取知识的成本降低了不少,博主也推荐使用ChatGpt之类的工具来提高学习效率。
2.域名
通过 www.baidu.com,我们可以很明显的辨认出这是百度的网址,其实这就是百度的域名,那我们再来看39.156.66.14,这里你可能会感觉有点懵逼,其实这也是百度的网址,不信博主复制粘贴到浏览器去访问一下,下面截图为证:
这一串数字是怎么得到的呢?
-
按下
win + r
,输入cmd
,按下回车。—— windows系统下 -
在命令窗口输入
ping www.baidu.com
这其实是百度的IP地址,通过它,我们就可以定位唯 一 一 台主机
,进而访问百度的服务器,获取相应的首页资源。此时我们再回到讨论的话题,域名相比ip地址,用户记忆的成本更低,这就是域名的好处
,但从专业的角度来看,域名背后其实绑定了ip地址,而且可能还不止一个
,如果你ping的ip地址跟我的不一样,就证明了这一点。
3.默认端口号
常见的默认端口号有:
- HTTP: 80
- HTTPS: 443
- FTP: 21
- SSH: 22
- Telnet: 23
- SMTP: 25
- POP3: 110
- IMAP: 143
- DNS: 53
- 端口号所在文件:
/etc/services
这些端口号一般是不允许被修改的,就像110在我们的脑中已经跟报警电话已经联系了起来,80就是http协议的默认端口,而且这些端口号在访问时一般浏览器是忽略的,如果改了还得在后面跟上: + 修改的端口号
,因为单凭ip地址只能锁定一台主机,还得指定端口号与相应的进程才能进行联系
,因为网络的本质就是进程间通信
。
4.URL
- 概念
- URL(
U
niformR
esourceL
ocator)是统一资源定位符的缩写,用于指定互联网上资源的位置和访问方式。简单的理解其实就是网址。
- URL(
- 组成
图解:
- 例1:ssh登录
- 例二:http协议
下面我们于查询字符串和片段标识符举两个例子:
- 字符串查询:
搜索引擎上输入
C++##
等带特殊字符的关键词。查看URL的查询参数:
- 如下图:
- 可见这些特殊字符是被编码了的,不过网上有现成的urlencode解码工具,进去将此字符串复制进行转换,可以查看到我们原来的查询的关键词。
- 如下图:
- 因此我们可以简单的理解查询不只是简单的查询,还要经过编码,从而
避免与网址的符号进行冲突
。
- 片段标识符:
- 当我们想要在网址中定位某一个网页的位置时,需要通过片段标识符。
- 博主上一篇文章的网址 :
https://blog.csdn.net/Shun_Hua/article/details/136523510?spm=1001.2014.3001.5501
。后面跟上和不跟上#_729
,对比效果即可明白片段标识符的作用。
如何找到片段标识符呢?
- 在网页中右键,选择选项中的检查。查看网页源代码。
- 按下
ctrl + f
在搜索框 搜索id
这个标签。
- 例:
- 鼠标移动至此,可在网页上看到对应的效果,即标记位置信息。
二、请求与响应
1.抓包工具
- fiddler,需要输入认证信息之后才可进行下载。
- postman, 外网的访问会有些慢,需要使用魔法,或许访问不上。
- apifox,国内的比较好用。
2.基本框架
我们先使用telnet工具进行简单的HTTP请求,查看请求与响应的格式:
因此可以大致列出请求与响应的基本框架:
穿插知识:
- 短连接:浏览器通常建立连接只能发一个请求,然后收一个响应,之后断开连接。若想再发送一个请求,只能再次申请连接,这适用于
无需多数据传输,无需保持连接,Http/1.0采用的是短连接
。- 长连接:浏览器通常建立连接之后会保持一段时间,直接可以进行多次数据的传输,可以一次发送多个请求,接收多个响应,在无数据传输之后会断开连接。相比短连接减少因频繁建立和关闭连接而产生的额外开销,提高通信效率,尤其
适用于需要频繁交换数据的场景,Http/1.1版本支持长连接
。- 说明:在请求报头中如果有
Connection: keep-alive
,则意味申请长连接,申请成功时,会在响应报头处添加:Connection: keep-alive
。
3.简易实现
在简易的了解Http的请求和响应的框架之后,我们可以通过代码,编写一个简单的Http服务器,并且制作一个简单的网页,来逐步理解Http的请求和响应。
3.1 HttpServer
在之前的文章,我们实现过守护进程,日志,封装基于TCP的socket等小组件,下面避免代码冗余就不再给出,下面的HttpServer其实就是一个基于TCP协议的服务端,写多了不管什么类型的服务端就是一种套路:
- 随机绑定端口与IP地址进行初始化。
- 对服务端进行初始化,即创建,绑定,监听套接字。
- 启动服务端,接收请求,建立链接,提供服务。
- 提供服务,其实就是将接收信息并对信息进行处理并返回。
关键就在于这个处理逻辑,按照什么方式处理,就决定了服务端是什么类型的。
- 实现代码:
#pragma once
#include<iostream>
#include<fstream>
#include<functional>
//容器
#include<vector>
#include<unordered_map>
//网络接口
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>//小组件
#include "../Tools/Log.hpp"
#include "../Tools/Socket.hpp"
using cal_t = function<string(string&)>;
string default_ip = "0.0.0.0";
uint16_t default_port = 8080;
class HttpServer;
struct PthreadData
{PthreadData(int sockfd,HttpServer* hsp):fd(sockfd),hp(hsp){}int fd;HttpServer* hp;
};
class HttpServer
{
public:HttpServer(uint16_t port = default_port,\cal_t signal = nullptr,string ip = default_ip):_sockfd(port,ip){}void Init(){_sockfd.Socket();//使端口号可以重复被使用,之后的TCP内容中会详谈。int opt = 1;setsockopt(_sockfd.GetSocket(),SOL_SOCKET,\SO_REUSEADDR|SO_REUSEPORT\,&opt,sizeof(opt));_sockfd.Bind();_sockfd.Listen();}static void *Routine(void* args){pthread_detach(pthread_self());auto thp = static_cast<PthreadData*>(args);HttpServer* hp = thp->hp;int fd = thp->fd;hp->Server(fd);return nullptr;}void Run(){for(;;){sockaddr_in client;socklen_t len;int fd = _sockfd.Accept(&client,&len);pthread_t tid;pthread_create(&tid,nullptr,Routine\,new PthreadData(fd,this));}}void Server(int fd){string mes;for(;;){mes += _sockfd.Read(fd);if(mes == "") break;//处理信息string echo_mes = cal(mes);int num = _sockfd.Write(fd,echo_mes);if(num == 0) break;}_sockfd.Close(fd);}
private:Sock _sockfd;cal_t cal;
};
3.2 HttpRequest
如下是我们实现处理请求类的宏观框架,读者有个大致的认识即可,博主下面会分别行进行实现,逐一进行讲解。
- 实现代码:
struct HttpRequest
{ //构造函数。HttpRequest();//从请求中获取一个完整的报文string InCode(string& str);//从报文中将请求的信息进行打散。bool Deserialize(string& str);//对请求报头解析并获取对应的内容。void Prase()//从指定目录中读取相关消息并进行返回。string ReadFromFile(const string& path)//获取返回网络的文件的类型。string GetContentType()//解析URL获取对应的网络资源。string GetSourse();//处理服务器收到的请求。string HanderHttpMes(string &mes);
public://正文之前的部分vector<string> infors;//提供文件在网络中的类型。unordered_map<string,string> content_type;//请求方法,大多数为POST和GET方法。string Method;//统一资源定位符。string Url;//URL里面可能有读取文件信息,请求的都是网页文件。string suffix = ".html";//HTTP的版本,一般为1.1或者1.0的。string Version; //请求正文,一般来说响应是没有的。string content;//获取资源在服务器的路径,即根目录。const string root = "./wwwroot";
};
- 主程序:
#include<iostream>
#include<memory>#include "httpserver.hpp"void Usage(char* pragma_name)
{cout << endl << "Usage: " << pragma_name \<< " + port[8000-8888]" << endl << endl;
}
int main(int argc,char* argv[])
{if(argc != 2){Usage(argv[0]);return 1;}uint16_t port = stoi(argv[1]);HttpRequest req;std::unique_ptr<HttpServer> htp(new HttpServer(port,\bind(&HttpRequest::HanderHttpMes,&req,placeholders::_1)));//bind函数:指定类域,固定this指针,以及参数,从而封装//出了一个返回值为string类型,参数为string&的函数。htp->Init();htp->Run();return 0;
}
- 对请求的处理和程序的运行有了宏观的认识之后,下面我们先来编写一段代码,在网页中打印出简单的消息。
- HanderHttpMes的实现:
3.2.1 version1
version1:打印出简单的信息。
string HanderHttpMes(string &mes){//避免mes过长,我们将其清空。mes = "";//空行string empty_line = "\r\n"; //状态行string state_line = "HTTP/1.1 200 OK\r\n";//正文string text = "hello world\r\n"; //报文段string package_line = "Content-Length: " +\to_string(text.size()) + empty_line;//响应string response = state_line + package_line +\empty_line + text;return response;}
- 运行结果:
- 效果:
看到效果之后,我们便可大致明白,浏览器其实就是接收信息的客户端,并按照自定义协议将信息给上层用户进行呈现。
运用知识:
Content-Length:【空格】【正文段长度】【\r\n】
—— 状态行信息,用于浏览器的获取正文段数据,并按照指定的方式呈现出来,这里我们只是打印出了文字。
- 缺陷:不管浏览器给我们发送什么请求,我们都只会返回hello world进行响应。
3.2.2 version2
version2: 完成请求的解析,提取出url,返回对应的网页资源。
- 请求解析。
- 思路:
1. 首先我们从缓存区中提取的不知道是否是一个完整的报文。
2. 因此我们应找到完整报文的解析符 ——\r\n\r\n
。
3. 一般情况下,浏览器是不会发送正文段的,因此我们按照没有发送正文段的报文进行解析处理。- 拓展:我们可以看已经截取的请求报头中查看是否有Content-Length字段,如果有则有正文,解析其后的数据长度,截取正文段即可。
- InCode
string InConde(string& str){string splite_str = "\r\n\r\n";size_t pos = str.find(splite_str,0);//如果没有找到说明不是一个完整的报文。if(pos == string::npos){return "";}int len = pos + splite_str.size();string package = str.substr(0,len);//将报文进行丢弃,便于截取下一次请求的报文。str.erase(0,len);return package; }
- 打散请求
- 思路:
因为都是以\r\n
以一行的形式进行呈现的,因此我们只需以\r\n
截取出每一行即可,然后添加到类型为vector<string> 的infors
即可。
- Deserialize
bool Deserialize(string& str){//先看是否有完整的报文string datagram = InConde(str);int cur = 0;while(true){size_t pos = datagram.find(line_break,cur);//从cur位置开始寻找。//如果没有就说明解析出错了。if(pos == string::npos) return false;string line = datagram.substr(cur,pos - cur); //截取pos - cur长度。cur = pos + line_break.size();//跳过line_breakif(line.empty()) break; //读取到空行。infors.push_back(line);}return true;}
- 提取状态行。
- 思路:
- 这里报文都存在
infors中
, 请求报头都在infors[0]
中,因此我们将其解析出来即可。- 格式为:
[请求方法][空格][Url][空格][HTTP版本]
,以空格分隔出每一个元素即可。
除此之外,因为我们要从url中解析出相应的返回资源,下面我们列出第一次访问网址浏览器发送的两次请求:
- 说明: 第一次请求的是主页资源,主页资源的url也可以为 /index.html,第二次请求的是网页标签的logo。
- 举个百度标签的logo:
根据url解析出相应的文件信息,我们可以据此返回相应的资源了。
- Prase
void Prase(){//对一行的资源进行处理string state_line = infors[0]; //[请求方法][空格][Url][空格][HTTP版本]auto left = state_line.find(space);auto right = state_line.rfind(space);//请求方法Method = state_line.substr(0,left);//urlUrl = state_line.substr(left + 1,right - left - 1);//请求的HTTP版本。Version = state_line.substr(right + 1);//看URL中是否带有文件信息,如果有则解析出来,默认为 ".html"auto pos = Url.rfind('.');if(pos != string::npos){suffix = Url.substr(pos);//默认为.htmlif(content_type[suffix] == "") suffix = ".html";}}
- 构造函数:
HttpRequest(){content_type[".jpg"] = "image/jpeg";content_type[".html"] = "text/html";content_type[".ico"] = "image/x-icon";}
- 说明:
- 响应时,我们返回对应网页资源时,得说明是什么类型的,浏览器会按照响应的方式进行解析。
- 我们只需再状态行添加
[Content-Type:][空格][资源文件的类型]
,比如:Content-Type: text/html
。
- 准备网页资源。
我们在当前目录下创建一个wwwroot
作为根目录,存放网页资源文件,一般的网页以 .html
结尾。
因此我们成员变量设置了:
const string root = "./wwwroot"; //获取资源在服务器的路径,即根目录。
我们这里创建一个index.html
,写一些网页信息:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Shun_Hua</title>
</head>
<body><h1 >欢迎来到我的主页!</h1>
</body>
</html>
- 说明:
- 首先博主采用的是vscode编写较为轻量,写起来也很轻松,按下
! 加上 Tab
可以快速生成一个网页框架。- 这里涉及一些前端的知识,博主在写项目时候总结了一下常用的,具体可见:详见目录前端编写模块 。
下面是如何找的过程,首先我们要从url获取到文件的信息,再跟网页的根目录进行拼接,具体实现如下:
- GetSourse
string GetSourse(){//根据Url,确定返回的资源string path = root;//主页资源。if(Url == "/" || Url == "/home.html")path += "/home.html";else{path += Url;}//从文件中读取消息。return ReadFromFile(path);}
下一步是从获取到的具体路径文件中,读取文件信息,作为正文段进行返回。
- ReadFromFile
string ReadFromFile(const string& path){//从文件中读取对应的内容。std::ifstream fs(path,ios_base::in);if(!fs.is_open()) return "404 Not Found";string content;//直接读取到文件的结尾fs.seekg(0,fs.end);//获取文件的长度。auto len = fs.tellg();//回退到文件的长度。fs.seekg(0,fs.beg);//直接将内容读取出来,将内容打到进去,这是比较暴力但是比较简单的做法。content.resize(len);fs.read((char*)content.c_str(),content.size());return content;}
以上的代码写完之后,我们可以再写一个更加高级的处理消息的函数:
- HanderHttpMes
string HanderHttpMes(string &mes){HttpRequest req;//首先对mes进行解析,获取完整的报文,解析失败返回空串。if(!req.Deserialize(mes)) return "";//其次解析出报头信息。req.Prase();//从Url中获取相应的网页资源。string text = req.GetSourse(); //正文string empty_line = "\r\n"; //空行string state_line = "HTTP/1.1 200 OK\r\n";//状态行string package_line = "Content-Length: " \+ to_string(text.size()) + empty_line;string content_type_line = "Content-Type: "\+ content_type[suffix] + empty_line;string response = state_line + package_line + empty_line + text;return response;}
- 效果:
- 返回的响应:
下面我们来一点前端的知识,让页面更加丰富多采一点:
- 增加网页标签logo
- 推荐网站:免费Favicon.ico图标在线生成器
- 这里我输入文字:舜华,进行自动生成。或者直接用现成的也可以。
- 点击图片下载保存到能找到的文件夹。
- 在Linux会话窗口使用:
rz -E
命令,将.ico
文件上传到Linux的存放网页文件的目录下。
然后我们再刷新网页,看一看效果:
- 有总比没有强,虽然颜色有点重,hhh。
此后,我们可以直接在网页文件中编写内容,服务器启动着,浏览器刷新即可更新出新的网页内容。
- 说明:以下所有更新文件都在
./wwwroot
路径下。
更新网页内容:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Shun_Hua</title>
</head>
<body><h1 >欢迎来到我的主页!</h1><!-- >更新内容,添加网页链接,可以跳转到指定网页 <--><a href="http://59.110.171.164:8888/"> 回到主页 </a></br> <!-- >回车换行的意思<--><a href="http://59.110.171.164:8888/tail.html"> 尾页 </a>
</body>
</html>
添加尾页内容:
- tail.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>尾页</title>
</head>
<body><h1>欢迎来到尾页!</h1><p>ps:功能开发中……</p><a href="http://59.110.171.164:8888/"> 回到主页 </a>
</body>
</html>
刷新界面:
在尾页添加图片:
- 图片 ——1.png
- tail.html
<!-- >说明:未补充内容同上 <-->
<body><h1>欢迎来到尾页!</h1><p>ps:功能开发中……</p><a href="http://59.110.171.164:8888/"> 回到主页 </a><br><img src = "./1.jpg" alt="实在抱歉" width="200px" height="200px"><!-- >加载对应的图片,设置图片加载失败时的提示,设置图片的宽度和高度 <-->
</body>
效果:
- 综上所述,我们使用一点点前端知识,将网页变的不至于那么单调,简单的完成与用户进行交互。
- 说明:以上都是请求成功的情况,那有没有请求失败的的情况呢?下面我们继续深入了解
响应行和响应报头
。
3.2.3 version3
- version3: 学习响应行和响应报头。
- 重定向
- 状态码:3XX,重定向,需要进一步的操作以完成请求。这里使用 302 Found。
- 状态行: 既然重定向了,我们还得告诉浏览器的重定向的地址是什么,这里我们使用302,状态行表示成:
[Location:][空格][网址][\r\n]
。
- HanderHttpMes
string HanderHttpMes(string &mes){HttpRequest req;string state_line = "HTTP/1.1 302 Found\r\n";//状态行string location_line = "Location: https://www.baidu.com\r\n";string empty_line = "\r\n"; //空行string response = state_line + location_line + empty_line;return response;}
- 效果:
2. 网页资源不存在
- 状态码:4XX,客户端错误,请求包含语法错误或无法完成请求。这里使用 404 Not Found。
- 状态行: 既然找不到,我们就返回一个表示找不到的网页即可。
- HanderHttpMes
string HanderHttpMes(string &mes){//如果解析出来的Url不存在,我们可以直接返回错误界面,//这里我们只是简单的演示一下效果。mes.resize(0);HttpRequest req;string text = ReadFromFile(root + "/errno.html") + "\r\n";string state_line = "HTTP/1.1 404 Not Found\r\n";//状态行string len_line = "Content-Length: " + to_string(text.size()) + "\r\n"; string empty_line = "\r\n"; //空行string response = state_line + len_line + empty_line + text;return response;}
- errno.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>404 Not Found</title>
<style>
body {
text-align: center;
padding: 150px;
}
h1 {
font-size: 50px;
}
body {
font-size: 20px;
}
a {
color: #008080;
text-decoration: none;
}
a:hover {
color: #005F5F;
text-decoration: underline;
}
</style>
</head>
<body>
<div>
<h1>404</h1>
<p>页面未找到<br></p>
<p>
您请求的页面可能已经被删除、更名或者您输入的网址有误。<br>
请尝试使用以下链接或者自行搜索:<br><br>
<a href="https://www.baidu.com">百度一下></a>
</p>
</div>
</body>
</html>
- 说明:网上有现成的,直接拿来用即可。
- 效果:
- 设置cookie
概念:cookie是一种文本文件,会进行存储记录用户的相关信息,发送给服务器进行认证。
优点:下一次登录时,会直接用已经存储好的cookie文件,无需再次登录认证。
- 图解:
如何查看呢?下面我们以CSDN的首页进行举例。
说明:cookie文件是有保质期的,过期了cookie会无效,需要再次认证。
- HanderHttpMes
string HanderHttpMes(string &mes){//如果解析出来的Url不存在,我们可以直接返回错误界面,//这里我们只是简单的演示一下效果。HttpRequest req;if(!req.Deserialize(mes)) return "";req.Prase();string text = req.GetSourse();string state_line = "HTTP/1.1 200 OK\r\n";//状态行string len_line = "Content-Length: " + to_string(text.size()) + "\r\n";string cookie_line = "Set-Cookie: user=shun_hua&&password=123456\r\n"; string empty_line = "\r\n"; //空行string response = state_line + len_line + cookie_line + empty_line + text;return response;}
-
效果:
-
网页中的cookie文件:
- 这里总结一下对响应和请求的大致分类:
- 状态码
状态码 | 状态描述 |
---|---|
1XX | 信息,服务器收到请求,需要请求者继续执行操作 |
2XX | 成功,操作被成功接收并处理 |
3XX | 重定向,需要进一步的操作以完成请求 |
4XX | 客户端错误,请求包含语法错误或无法完成请求 |
5XX | 服务器错误,服务器在处理请求的过程中发生了错误 |
- 当我们使用具体的状态码时,查表即可,但是我们要对状态码的分类比较清楚,上面我们使用了404,302,200进行了演示。
- Header
Header | 描述 |
---|---|
Content-Type: | 数据类型(text/html等) |
Content-Length: | Body的长度 |
Host: | 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上; |
User-Agent: | 声明用户的操作系统和浏览器版本信息; |
referer: | 当前页面是从哪个页面跳转过来的; |
location: | 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问; |
Cookie: | 用于在客户端存储少量信息. 通常用于实现会话(session)的功能 |
- 常用状态码与响应头
- 请求方法
请求方法 | 描述 |
---|---|
GET | 请求指定的页面信息,并返回实体主体。 |
POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。 |
HEAD | 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 |
PUT | 从客户端向服务器传送的数据取代指定的文档的内容。 |
DELETE | 请求服务器删除指定的页面。 |
CONNECT | HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。 |
OPTIONS | 允许客户端查看服务器的性能。 |
TRACE | 回显服务器收到的请求,主要用于测试或诊断。 |
PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新 。 |
- 说明:大多数请求都是Get和Post,其它的我们当做了解即可。
总结
- 我们认识了一些现成的应用层协议,比如SMTP,FTP,SSH等。
- 了解了Http的基本概念,比如域名,默认端口号,统一资源定位符。
- 介绍了三个抓包工具,fiddler,postman,apifox。
- 使用telnet工具发送请求,接收响应。并列出了请求和响应的框架,据此学习了长连接和短连接的知识。
- 编程实践,编写一个网络的Server服务和Request类处理请求,通过此学习了常用的请求行的状态码,请求报头等,一些网页的前端知识,比如标题logo,图片,链接,编写了一个简单网页。
- 下期预告:
我们此文提及了cookie一般是含认证信和密码之类的信息
,但http是明文传输的
,这就导致了数据在网络中是不安全的,这就涉及到了加密,据此引出下篇文章要讨论的Https
,敬请期待!。
尾序
我是舜华,期待与你的下一次相遇!
相关文章:

【Linux进阶之路】HTTP协议
文章目录 一、基本概念1.HTTP2.域名3.默认端口号4.URL 二、请求与响应1.抓包工具2.基本框架3.简易实现3.1 HttpServer3.2 HttpRequest3.2.1 version13.2.2 version23.2.3 version3 总结尾序 一、基本概念 常见的应用层协议: HTTPS (HyperText Transfer Protocol Sec…...
股市新手福音:河北源达“财源滚滚”让投资变得更简单
在浩渺的股市海洋中,每一位投资者都渴望找到一把能够指引航向的罗盘。尤其是对于股市新手来说,面对复杂的市场环境、纷繁的个股信息以及不断变化的投资策略,如何快速入门、精准选股,无疑是一大挑战。而河北源达信息技术股份有限公…...
2024.02.14 校招 实习 内推 面经
绿*泡*泡VX: neituijunsir 交流*裙 ,内推/实习/校招汇总表格 1、校招&社招 | 中国电子信息产业集团有限公司校园招聘 校招&社招 | 中国电子信息产业集团有限公司校园招聘 2、校招&社招 | 中核光电2024年春季校园招聘开启! 校…...

5.Java并发编程—JUC线程池架构
JUC线程池架构 在Java开发中,线程的创建和销毁对系统性能有一定的开销,需要JVM和操作系统的配合完成大量的工作。 JVM对线程的创建和销毁: 线程的创建需要JVM分配内存、初始化线程栈和线程上下文等资源,这些操作会带来一定的时间和…...
llama2c(4)之forward、sample、decode
1、forward float* logits forward(transformer, token, pos); 输入transformer的参数,当前token,pos位置,预测出下一个token的预测值(用矩阵乘,加减乘除等运算构成Transformer) 其中,logits如…...

20240312-2-贪心算法
贪心算法 是每次只考虑当前最优,目标证明每次是考虑当前最优能够达到局部最优,这就是贪心的思想,一般情况下贪心和排序一起出现,都是先根据条件进行排序,之后基于贪心策略得到最优结果。 面试的时候面试官一般不会出贪…...

前端 --- HTML
1. HTML 结构 1.1 HTML 文件基本结构 <html><head><title>第一个html程序</title></head><body>hello world!</body> </html> html 标签是整个 html 文件的根标签(最顶层标签)head 标签中写页面的属性.body 标签中写的是页…...
curl c++ 实现HTTP GET和POST请求
环境配置 curl //DV2020T环境下此步骤可省略 https://curl.se/download/ 笔者安装为7.85.0版本 ./configure --without-ssl make sudo make install sudo rm /usr/local/lib/curl 系统也有curl库,为防止冲突,删去编译好的curl库。 对以json数据的解析使…...

12、设计模式之代理模式(Proxy)
一、什么是代理模式 代理模式属于结构型设计模式。为其他对象提供一种代理以控制对这个对象的访问。 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 二、分类 代理模式分为三类&#…...
springboot集成Quartz定时任务组件
文章目录 前言一、Quartz 是什么?下面是对 Java 中 Quartz 的主要概念的简单描述: 二、使用步骤总结 前言 平时开发中相信大家都经常用到定时任务吧,最近简单的就是直接使用Scheduled注解标注到方法上用注解的方式在项目运行时无法去对任务进…...
代码随想录算法训练营第38天—动态规划06 | ● 完全背包 ● *518. 零钱兑换 II ● 377. 组合总和 Ⅳ
完全背包 视频讲解:https://www.bilibili.com/video/BV1uK411o7c9 https://programmercarl.com/%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80%E5%AE%8C%E5%85%A8%E8%83%8C%E5%8C%85.html 题目描述:有n件物品和一个最多能…...
C语言每日一题(63)复写零
题目链接 力扣网 1089 复写零 题目描述 给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。 注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改,不…...
ElasticSearch聚合查询
数据准备 索引创建 PUT product {"mappings": {"properties": {"createtime": {"type": "date"},"desc": {"type": "text","fields": {"keyword": {"type": …...

【毕设级项目】基于AI技术的多功能消防机器人(完整工程资料源码)
基于AI技术的多功能消防机器人演示效果 竞赛-基于AI技术的多功能消防机器人视频演示 前言: 随着“自动化、智能化”成为数字时代发展的关键词,机器人逐步成为社会经济发展的重要主体之一,“机器换人”成为发展的全新趋势和时代潮流。在可预见…...

【一】【设计模式】类关系UML图
1. 继承(Generalization) 继承是对象间的一种层次关系,允许子类继承并扩展父类的功能。 UML线:带有空心箭头的直线,箭头指向基类(父类)。 class Parent {public void parentMethod() {System.…...
【DevOps基础篇】容器化架构基础设施监控方案
【DevOps基础篇】容器化架构基础设施监控方案 目录 【DevOps基础篇】容器化架构基础设施监控方案要监视什么不同监控系统方案比较1. Datadog2. Prometheus3. ELK(Elasticsearch、Logstash、Kibana)4. Sysdig5. 自行打造!如何选择总结推荐超级课程: Docker快速入门到精通 当…...

【QT】文件流操作(QTextStream/QDataStream)
文本流/数据流(二级制格式) 文本流 (依赖平台,不同平台可能乱码)涉及文件编码 #include <QTextStream>操作的都是基础数据类型:int float string //Image Qpoint QRect就不可以操作 需要下面的 …...

CentOS 7 devtoolset编译addressSanitizer版本失败的问题解决
在我的一个Cent OS7开发环境中,按https://yeyongjin.blog.csdn.net/article/details/134178420的方法升级GCC版本到8.3.1。 这两天,要用Google的addressSanitizer检验内存问题,加上编译参数后,却发现编译不通过。configure时直接退…...

ubuntu2004桌面系统英伟达显卡驱动安装方法
#如何查看显卡型号 lspci | grep -i vga#----output------ 01:00.0 VGA compatible controller: NVIDIA Corporation Device 1f06 (rev a1)根据 Device 后的 值 进入网站查询 pci-ids.ucw.cz/mods/PC/10de?actionhelp?helppci #根据显卡型号,下载对应系统的驱动…...
Java通过Excel批量上传数据!!!
一、首先在前端写一个上传功能。 <template><!-- 文件上传 --><el-upload class"upload-demo" drag action"" :on-change"onChange" :auto-upload"false"><el-icon class"el-icon--upload"><up…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...