目录
[2.1 请求方法](#2.1 请求方法)
[2.2 telnet](#2.2 telnet)
[2.3 网页根目录](#2.3 网页根目录)
[2.3.1 概念](#2.3.1 概念)
[2.3.2 构建一个首页](#2.3.2 构建一个首页)
[2.4 GET与POST方法](#2.4 GET与POST方法)
[2.4.1 提交参数](#2.4.1 提交参数)
[2.4.2 GET与POST提交参数对比](#2.4.2 GET与POST提交参数对比)
[2.4.3 GET和POST对比](#2.4.3 GET和POST对比)
[3.1 状态码分类](#3.1 状态码分类)
[3.2 3XXX状态码](#3.2 3XXX状态码)
[3.2 长连接与短链接](#3.2 长连接与短链接)
[4.1 Cookie](#4.1 Cookie)
[4.1.1 Cookie的作用](#4.1.1 Cookie的作用)
[4.1.2 Cookie的存在形式](#4.1.2 Cookie的存在形式)
[4.1.3 Cookie的原理](#4.1.3 Cookie的原理)
[4.1.4 设置Cookie](#4.1.4 设置Cookie)
[4.2 Session](#4.2 Session)
[4.2.1 Session的引入](#4.2.1 Session的引入)
[4.2.2 Session的原理](#4.2.2 Session的原理)
1.http中常见的Header(KV结构)
content-length:该结构的作用是表示正文有多少个字节。空行的作用是保证可以识别报文被读完,而报文中的ContentLength保证报文被读完,防止将下一个http请求读到,保证信息的完整性。如果报头中的ContentLength不存在,则代表报文为空。
Connect-Type:正文的类型,使用Content-Type对照表进行查询。
Location:当发生跳转时,跳转的位置。
Connection:判断是否有长连接。
2.http请求方法
2.1 请求方法
GET:获取资源
POST:传输资源主体
PUT:传输文件
HEAD:获得报头
DELETE:删除文件
OPTIONS:询问支持的方法
TRACE:追踪路径。
CONNECT:要求用隧道协议连接代理
LINK:建立和资源之间的联系
UNLINK:断开连接关系
其中网站可以暴露给用户的方法一般只有三个:GET,POST,HEAD。
2.2 telnet
使用telnet指令可以作为客户端,向网页的服务端申请服务,首先对telnet指令进行安装:
sudo apt update
sudo apt install telnet
sudo apt update
sudo apt install xinetd telnetd
sudo systemctl enable xinetd
sudo systemctl start xinetd
telnet www.baidu.com 80 //连接百度网站的端口号80
ctrl+]进入telnet命令行,回车进入下一行
HEAD/HTTP/1.0
向百度服务器申请网页根目录(/)下的信息,客户回接收到一个1.0版本的http协议的信息。注意,是使用HEAD方法来进行申请的,因此只会得到一个报头的信息:

当我们使用GET方法就会得到报头和资源(报文信息):

2.3 网页根目录
2.3.1 概念
注意我们发送的请求中,有一个'/'代表网页根目录,网页根目录即.server所在的文件夹:

但是我们要向服务器申请的,一般是一个资源,最终应该是/a/b/c类似的东西,即访问c资源。因此就会有一个规定:
规定,申请网页根目录的时候,访问的是根目录中的首页资源,通常是一个html。
比如我们在浏览器中输入:IP地址:8080/,就会拿到对应浏览器的首页资源。基本所有的网站都有其对应的首页。
2.3.2 构建一个首页
同理,我们也可以在我们的云服务器上的网页根目录来构建一个首页资源:
cpp
string html_file=WWWROOT;
html_file+=HOMEPAGE;
//if(method=='\') path=./index.html //会获取报头中的method信息,此时将路径设为首页。
struct stat st;
stat(html_file.c_str(),&st);
std::string http_response = "http/1.0 200 OK\n";
http_response += "Content-Type: text/html;charset=utf8\n"; // text/plain,正文是普通的文本
http_response+="Content-Length: ";
http_response+=to_string(st.st_size);
http_response+="\n";
http_response += "\n"; //空行
std::ifstream in(html_file);
if(!in.is_open())
{
cerr<<"open html error"<<endl;
}
else
{
string content;
string line;
while(getline(in,line))
{
content+=line;
}
http_response+=content;
in.close();
}
send(sock,http_response.c_str(),http_response.size(),0);
close(sock);
建立一个html的文件,在服务端打开它,并读取其中的内容,放在正文中发送给客户端。客户端会自行解析html文件。
cpp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf_8">
</head>
<body>
<h3>hello myfriend!</h3>
</body>
</html>
2.4 GET与POST方法
2.4.1 提交参数
修改html代码,可以达到提交参数的目的:
cpp
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h5>hello 我是首页!</h5>
<h5>hello 我是表单!</h5>
<form action="/a/b/handler_from" method="GET">
姓名: <input type="text" name="name"><br/>
密码: <input type="password" name="passwd"><br/>
<input type="submit" value="登陆">
</form>
</body>
</html>
此时再进行访问,就可以看到这个界面:

2.4.2 GET与POST提交参数对比
当使用GET方法提交参数(输入姓名和密码)的时候,提交的信息会显示在URL中。

如果以POST方法提交参数(将method改成POST),提交的信息会显示在正文中。

2.4.3 GET和POST对比
对比一:
GET主要用于获取,是最常用的,占70%默认一般获取所有的网页都是GET方法,如果GET提交参数(它可以提交的!!),通过URL进行参数拼接,然后传递给服务端。
POST主要用于推送,是提交参数的常用方法,如果提交参数,一般是通过正文提交的。
对比二:
参数提交的位置不同,GET不私秘,会将重要的信息回显到输入框中,增加了被盗取的危险。POST比较私密(不代表安全),不会回显到浏览器URL的输入框中。
GET通过URL传参,而URL是有大小限制的
对比三:
如何选择:如果提交的参数不敏感,数量非常少,可以采用GET,否则使用POST。
GET和POST是前后端数据交换的重要方式。
3.状态码
3.1 状态码分类
通常来说,状态码分为五类:
1XX:information(信息性状态码),接收的请求正在处理。
2XX:Success(成功状态码),请求正常处理完毕。
3XX:Redirection(重定向状态码),需要进行附加操作以完成请求。
4XX:Client Error(客户端错误状态码),服务端无法处理请求。
5XX:Server Error(服务端错误状态码),服务器处理请求出错。
注意:由于应用层是人要参与的,人的水平参差不齐,http的状态码很多人不清楚该如何使用,又因为浏览器的种类太多了,导致可能对状态码的支持没有那么好,类似于404的状态码对浏览器没有指导意义,浏览器只会正常显示网页。这也就意味着404的页面需要程序员来编写。
3.2 3XXX状态码
3XXX状态码是有特殊意义的,代表重定向。
301:永久重定向。
302或307:代表临时重定向。
重定向:当访问一个网站的时候,会让我们跳转到另一个网址。
永久重定向:当用户访问一些老网址的时候,老网址会告诉浏览器,资源已经被搬运到其他的网址去了,此时会更新一些浏览器的缓存,然后跳转到新网址。当再次访问老网址的时候,就不会访问老网址了而是直接访问新网址。
临时重定向:当我们访问某种资源的时候,提示登录,跳转到登录页面,输入用户名和密码之后,再跳转回原来的页面。跳转网址是为了执行某一个任务,而不是资源搬迁。
重定向是需要浏览器提供支持的,浏览器必须能够认识到状态码,由服务端告知浏览器应该跳转到哪里。
cpp
string response="http/1/1 301 Permanently moved\n";
response+="Location: https://www.qq.com/\n";
response+="\n";
send(sock,response.c_str(),response.size(),0);
使用Location来将网页重定向到腾讯首页,此时访问该网站就会直接跳转到腾讯的首页了。
3.2 长连接与短链接
注意这里使用的是1.1,我们之前使用的都是1.0版本,而1.0版本代表的是短链接。
短链接的作用在于,我们申请服务器上所有资源的时候都是请求,响应然后断开连接。当访问一个由多个元素构成的网页的时候,http/1.0需要多次进行http请求。http是基于TCP进行通信的,TCP通信的时候要经过(建立连接,传输数据,断开连接),每一次http都需要执行这一过程。
当网页上有图片的时候(在html页面添加):
cpp
<img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fwww.2008php.com%2F09_Website_appreciate%2F10-07-11%2F1278861720_g.jpg&refer=http%3A%2F%2Fwww.2008php.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1663734890&t=27a504cab6d3d39a9b1d65cdf171784e" alt>
对于短链接来说,此时客户端在申请网页的同时,还会申请图片(在对应图片网站的客户端申请)。
服务端上有很多资源,一个网页中有很多资源,如果对每一个资源都发起http请求,是很麻烦的,因此引入了长链接。在通信的时候会复用同一个链接。
长连接可以减少频繁建立TCP链接,达到提高效率的目的。在报头属性中的Connection=keep-alive表示支持长链接,如果没有Connection属性或者Connection=close不支持长链接,我们的代码是短链接代码,如果想支持长链接需要在代码上做修改
4.Cookie与Session
4.1 Cookie
4.1.1 Cookie的作用
在我们访问网站的时候,登录之后,访问该网站的其他内容,网站是如何识别我们是否已经登录了呢?注意,http协议是不记录历史上的http的信息的。这并不是http协议本身需要解决的问题,当时http可以提供一些技术支持来保证网站具有会话保持功能。
比如我们登录的CSDN网站,刷新一次页面(重新进行一次资源请求,此时就不再需要登录了,这就是Cookie的作用。
在谷歌浏览器的上方有一个锁的图标,点击它就可以看到正在使用的Cookie了。

当我们将这些Cookie移除的时候(移除了所有Cookie信息,其中包括登录信息)时,再次刷新网站,就会发现需要我们来进行登录了。
登录之后发现Cookie信息又被重新存储了。
4.1.2 Cookie的存在形式
Cookie有两种存在形式,可以是一个文件(在主机的用户夹下可以找到),也可以是一个内存,它是与浏览器同生命周期的,当把浏览器关掉,就没有Cookie信息了。
4.1.3 Cookie的原理
在浏览器的角度看来,Cookie是一个浏览器中的文件,文件中存放的是用户的私密信息。
在http通信中,一旦该网站有Cookie,在发起任何请求的时候,都会在报头中自动携带Cookie信息。

4.1.4 设置Cookie
在服务端向客户端的响应中,可以使用Set-Cookie设置Cookie:
cpp
http_response+="Set-Cookie: id=1111\n";
http_response+="Set-Cookie: password=2222\n";
此时可以发现,进行访问的时候,浏览器处就有了Cookie的信息:

当再次访问的时候,服务器会接收到Cookie的内容:

4.2 Session
4.2.1 Session的引入
在了解了Cookie之后,如果有人盗取了我的Cookie文件,以我的身份来认证访问特定的资源,那么就会有安全隐患。
因此我们引入了Session,核心思路是将用户的私密信息保存在服务端。
4.2.2 Session的原理

此时就可以保证浏览器中的Cookie的信息是服务端文件的session_id,所有的http请求都会有浏览器自动携带的cookie中的session_id,后续server依旧可以认识client,也是一种会话保持的功能,但是我们还有cookie文件被泄露的风险。