Linux从青铜到王者第十六篇:Linux网络基础第二篇之HTTP协议

Posted 森明帮大于黑虎帮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux从青铜到王者第十六篇:Linux网络基础第二篇之HTTP协议相关的知识,希望对你有一定的参考价值。

系列文章目录



前言


一、HTTP协议的概念

  • HTTP(HyperText Transfer Protocol,超⽂本传输协 )的协议。
  • HTTP是⽆连接, ⽆状态, ⼯作在应⽤层的协议。
  • ⽆连接理解为: http协议本身是没有维护连接信息的, http的数据会交给⽹络协议栈传输层的TCP协议, ⽽TCP是⾯向连接的。 ⼤家注意区别。
  • ⽆状态: HTTP 协议⾃身不对请求和响应之间的通信状态进⾏保存。也就是说在 HTTP 这个级别,协议对于发送过的请求或响应都不做持久化处理。
  • 【问题一】HTTP是无连接的,不会维护连接信息,那么它是否是可靠传输呢?
  • HTTP是可靠传输的,虽然HTTP无连接,自身不会维护连接信息,但是,它的数据最终会交给传输层的TCP协议,而TCP协议是可靠传输的,因此HTTP协议是可靠传输的。

二、HTTP协议URL的解释

平时我们俗称的 “网址” 其实就是说的 URL。
以下图为例对URL的各部分进行说明:

  • http:明文传输,默认端口是80端口
  • https:加密传输(一般用ssl非对称加密方式,会对http双方发送的数据进行加密,公钥:客户端所持有,私钥:服务端所持有),默认端口是443端口。

像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现。比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义。

  • 转义的规则如下:
  • 将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。
  • urlencode:将字符转换成为16进制。
  • urlecode:将16进制数据转换成字符。
  • 使⽤ http: 或 https: 等协议⽅案名获取访问资源时要指定协议类型。不 区分字⺟⼤⼩写,最后附⼀个冒号(:)。
  • 登录信息(认证) 指定⽤户名和密码作为从服务器端获取资源时必要的登录信息(身份 认证)。此项是可选项。
  • 服务器地址 ,必须指定待访问的服务器地址。地址可以是类似 hackr.jp 这种 DNS 可解析的名称,或是192.168.1.1 这类 IPv4 地址 名,还可以是 [0:0:0:0:0:0:0:1] 这样⽤⽅括号括起来的 IPv6 地址名。
  • 服务器端⼝号 指定服务器连接的⽹络端⼝号。此项也是可选项,若⽤户省略则⾃动 使⽤默认端⼝号。
  • 带层次的⽂件路径 指定服务器上的⽂件路径来定位特指的资源。
  • 查询字符串针对已指定的⽂件路径内的资源,可以使⽤查询字符串传⼊任意参 数。此项可选。
  • ⽚段标识符 使⽤⽚段标识符通常可标记出已获取资源中的⼦资源(⽂档内的某个 位置)。该项也为可选项。

三、HTTP协议的数据流

四、HTTP协议格式

1.HTTP请求

HTTP 协议规定,请求从客户端发出,最后服务器端响应该请求并返回。换句话说,肯定是先从客户端开始建⽴通信的,服务器端在没有接收到请求之前不会发送响应。

请求格式如下图

验证:
假如我们在百度搜索C++,然后按F12打开开发者工具,此时我们会看到如下界面:


此时打开的开发者工具框什么都没有,是因为内容已经加载过了,才打开的开发者工具,只需要刷新页面即可看到如下图所示界面:


打开NetWork,在然后随便点开一个请求资源名称,如下图所示::

  • 总结:
  • 请求⾸⾏:⽅法 URI 协议版本。
  • 请求体: key:value的属性⾏。
  • 空⾏。
  • 正文。

2.HTTP响应

  • 总结:
  • 响应⾸⾏:协议版本 状态码 状态码解释。
  • 响应体: key:value的属性⾏。
  • 空⾏。
  • 正文。

五、HTTP协议格式图解

六、HTTP协议版本

HTTP/0.9(不常用)

HTTP/0.9 HTTP 于 1990 年问世。那时的 HTTP 并没有作为正式的标准被建立。 现在的 HTTP 其实含有 HTTP1.0 之前版本的意思,因此被称为 HTTP/0.9。

HTTP/1.0 (常用)

HTTP/1.0 HTTP 正式作为标准被公布是在 1996 年的 5 月,版本被命名为 HTTP/1.0,并记载于 RFC1945。虽说是初期标准,但该协议标准至今仍被广泛使用在服务器端。

HTTP/1.1(常用)

HTTP/1.1 1997 年 1 月公布的 HTTP/1.1 是目前主流的 HTTP 协议版本。当初的 标准是 RFC2068,之后发布的修订版 RFC2616 就是当前的最新版 本。

HTTP/2.0(不常用)

HTTP/2.0 新 一代 HTTP/2.0 正在制订中,但要达到较高的使用覆盖率,仍需假以时日

七、HTTP协议请求方法

1. GET:获取资源

GET 方法用来请求访问已被 URI 识别的资源。指定的资源经服务器端解析后返回响应内容。也就是说,如果请求的资源是文本,那就保持原样返回;(GET既能从服务器中去获取数据,也能向服务器中提交少量数据,提交的数据在URL中)

2.POST:传输实体主体

虽然用 GET 方法也可以传输实体的主体,但一般不用 GET 方法进行传输,而是用 POST 方法。虽说 POST 的功能与 GET 很相似,但 POST 的主要目的并不是获取响应的主体内容。(给服务器提交某些数据,提交的数据在正文中)

eg:假设我们要在某个网页进行登录,使用POST请求就会将我们的账号,密码放在请求正文中进行提交

如下图所示我们可以看到POST请求,且在请求正文中可以看到刚才输入的账号密码和验证码:

3.PUT:传输⽂件

PUT ⽅法⽤来传输⽂件。就像 FTP 协议的⽂件上传⼀样,要求在请求报⽂的主体中包含⽂件内容,然后保存到请求 URI 指定的位置。 但是,鉴于 HTTP/1.1 的 PUT ⽅法⾃身不带验证机制,任何⼈都可以上传⽂件 , 存在安全性问题,因此⼀般的 Web ⽹站不使⽤该⽅法。

4.HEAD:获得报⽂⾸部

HEAD方法和GET方法一样,只是不返回报文主体部分,用来确认资源的有效性。HEAD方法是不需要服务端返回响应正文的,使用HEAD方法,服务器只会返回响应首行、响应报头、空行。

5.DELETE:删除⽂件

DELETE ⽅法⽤来删除⽂件,是与 PUT 相反的⽅法。但是, HTTP/1.1 的 DELETE ⽅法本身和 PUT ⽅法⼀样不带验证机制,所以⼀般的 Web ⽹站也不使⽤ DELETE ⽅法。

6.OPTIONS:询问⽀持的⽅法

OPTIONS方法用来查询针对请求URL指定的资源支持的方法。即客户端询问当前服务器都支持哪些方法。

八、HTTP协议请求方法总结

九、HTTP状态码&状态码解释

1.HTTP状态码类别

2.2XX 成功

2XX 的响应结果表明请求被正常处理了。

200(OK)

表示从客户端发来的请求在服务器端被正常处理了。

204(No Content)

请求处理成功了,但没有资源要返回(没有正文):

206(Partial Content)

客户端进行了范围请求,服务器成功执行这一请求:

3.3XX 重定向


3XX响应结果表明浏览器需要进行附加操作以完成请求。

301(Moved Permanently) 永久性重定向

告诉服务器某一资源已被永久放在另一个URL中,以后访问需访问新的URL

302(Found) 临时性重定向

客户端要请求的资源临时被放到新的服务器中,以后访问此资源还是访问这个旧服务器

303(See Other)

要访问的资源已经更新:

4.4XX 客户端错误

4XX的响应结果表明客户端发生错误。

400(Bad Request)

服务端无法理解客户端发送的请求:请求格式错误

401(Unauthorized)

认证失败

403(Forbidden)

客户端请求访问某一资源被服务器拒绝了,即没有资格(权限)访问某一资源

404(Not Found)

服务器无法找到客户端请求的资源

5.5XX 服务器错误

5XX的响应结果表明服务器处理请求出错

500(Internal Server Error)

该状态码表明服务器端在执行请求时发生错误,也有可能是Web应用存在的bug或某些临时的故障

② 503(Service Unavailable)

服务器繁忙

十、HTTP常见Header

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

cookie和session都是用来跟踪浏览器用户身份的会话方式。

  • Cookie的工作原理
  • 浏览器端第一次发送请求到服务器端
  • 服务器端创建Cookie,该Cookie中包含用户的信息,然后将该Cookie发送到浏览器端
  • 浏览器端再次访问服务器端时会携带服务器端创建的Cookie
  • 服务器端通过Cookie中携带的数据区分不同的用户
  • Session的工作原理
  • 浏览器端第一次发送请求到服务器端,服务器端创建一个Session,同时会创建一个特殊的Cookie(name为JSESSIONID的固定值,value为session对象的ID),然后将该Cookie发送至浏览器端。
  • 浏览器端发送第N(N>1)次请求到服务器端,浏览器端访问服务器端时就会携带该name为JSESSIONID的Cookie对象。
  • 服务器端根据name为JSESSIONID的Cookie的value(sessionId),去查询Session对象,从而区分不同用户。name为JSESSIONID的Cookie不存在(关闭或更换浏览器),返回1中重新去创建Session与特殊的Cookiename为JSESSIONID的Cookie存在,根据value中的SessionId去寻找session对象value为SessionId不存在(Session对象默认存活30分钟),返回1中重新去创建Session与特殊的Cookievalue为SessionId存在,返回session对象。

  • Cookie和Session的区别:

  • Cookie和Session的区别对比:
  • cookie数据存放在客户的浏览器上,session数据放在服务器上。
  • cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session。
  • session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用COOKIE。
  • 单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K。
  • 所以:将登陆信息等重要信息存放为SESSION;其他信息如果需要保留,可以放在COOKIE中。

十一、HTTP协议和浏览器的交互

实现一个最简单的HTTP服务器, 只在网页上输出 “hello world”; 只要我们按照HTTP协议的要求构造数据, 就很容易能做到。

     1	#include<iostream>
     2	#include<sys/types.h>
     3	#include<sys/socket.h>
     4	#include<errno.h>
     5	#include<stdio.h>
     6	#include<netinet/in.h>
     7	#include<arpa/inet.h>
     8	#include<stdlib.h>
     9	#include<string.h>
    10	#include<unistd.h>
    11	#include<sstream>
    12	using namespace std;
    13	
    14	int main()
    15	{
    16	    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    17	    if(sockfd<0)
    18	    {
    19	        perror("socket");
    20	        return 0;
    21	    }
    22	
    23	    struct sockaddr_in addr;
    24	    addr.sin_port=htons(20000);
    25	    addr.sin_family=AF_INET;
    26	    addr.sin_addr.s_addr=inet_addr("172.16.0.9");
    27	
    28	    int ret=bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
    29	    if(ret<0)
    30	    {
    31	        perror("bind");
    32	        return 0;
    33	    }
    34	
    35	    ret=listen(sockfd,1);
    36	    if(ret<0)
    37	    {
    38	        perror("listen");
    39	        return 0;
    40	    }
    41	
    42	    struct sockaddr_in cli_addr; //客户端的协议栈
    43	    socklen_t cli_addrlen=sizeof(cli_addr);
    44	    int newsockfd=accept(sockfd,(struct sockaddr*)&cli_addr,&cli_addrlen);
    45	    if(newsockfd<0)
    46	    {
    47	        perror("accept");
    48	        return 0;
    49	    }
    50	    cout<<"accept new connect form client:"<<inet_ntoa(cli_addr.sin_addr)<<" "<<ntohs(cli_addr.sin_port);
    51	
    52	    while(1)
    53	    {
    54	        char buf[1024]={0};
    55	        ssize_t recv_size=recv(newsockfd,buf,sizeof(buf)-1,0);
    56	        if(recv_size<0)
    57	        {
    58	            perror("recv");
    59	            continue;
    60	        }
    61	        else if(recv_size==0)
    62	        {
    63	            cout<<"peer close connect!"<<endl;
    64	            close(newsockfd);
    65	            return 0;
    66	        }
    67	
    68	        cout<<"buf:"<<buf<<endl;
    69	        memset(buf,'\\0',sizeof(buf));
    70	
    71	        string body="<html><h1>hello world</h1></html>";
    72	        stringstream ss;
    73	      ss<<"HTTP/1.1 200 OK\\r\\n";
    74	        ss<<"Content-Type: text/html\\r\\n";
    75	        ss<<"Content-length: "<<body.size()<<"\\r\\n";
    76	     
    77	       // ss<<"HTTP/1.1 302 Found\\r\\n";
    78	       // ss<<"Location: https://www.baidu.com/\\r\\n";
    79	        ss<<"\\r\\n";
    80	
    81	        send(newsockfd,ss.str().c_str(),ss.str().size(),0);
    82	        send(newsockfd,body.c_str(),body.size(),0);
    83	
    84	    }
    85	    close(sockfd);
    86	    return 0;
    87	}

编译, 启动服务. 在浏览器中输入 http://[ip]:[port], 就能看到显示的结果 “Hello World”。

此处我们使用 9090 端口号启动了HTTP服务器. 虽然HTTP服务器一般使用80端口,但这只是一个通用的习惯. 并不是说HTTP服务器就不能使用其他的端口号。

把返回的状态码改成303等, 看浏览器上分别会出现什么样的效果。

    77	       ss<<"HTTP/1.1 302 Found\\r\\n";
    78	        ss<<"Location: https://www.baidu.com/\\r\\n";
    79	        ss<<"\\r\\n";


这里发生了重定向的结果!


💬总结

以上就是今天要讲的内容,本文详细介绍了应用层HTTP协议的实现使用,网络提供了大量的方法供我们使用,非常的便捷,我们务必掌握。希望大家多多支持!另外如果上述有任何问题,请懂哥指教,不过没关系,主要是自己能坚持,更希望有一起学习的同学可以帮我指正,但是如果可以请温柔一点跟我讲,爱与和平是永远的主题,爱各位了。加油啊!

以上是关于Linux从青铜到王者第十六篇:Linux网络基础第二篇之HTTP协议的主要内容,如果未能解决你的问题,请参考以下文章

Love2d从青铜到王者第十六篇:Love2d之动画(Animation)

Linux从青铜到王者第六篇:Linux进程概念第二篇

C++从青铜到王者第二十六篇:哈希

Linux从青铜到王者第十四篇:Linux网络基础第一篇

Linux从青铜到王者第十五篇:Linux网络编程套接字两万字详解

Linux从青铜到王者第十八篇:Linux网络基础第二篇之TCP协议