HTTP协议

举报
End、断弦 发表于 2022/04/02 11:35:32 2022/04/02
【摘要】 http协议概念 URL http协议格式 http请求 抓包 http响应 http方法 http的状态码 http常见的Header https 实现一个简单的http服务器

http协议概念

HTTP(HyperText Transfer Protocol,超⽂本传输协 )的协议。

  • http是无连接的,无状态的,简单快速的工作在应用层的协议。
  • 无连接:http本身没有维护连接信息,它会把数据交给传输层的TCP,当TCP建立好连接后,http直接发送数据,不关心TCP的细节
  • 无状态:http本身无状态,不会记录用户信息
  • 简单快速:http采用的是短连接进行文本传输的

URL

虽然我们说, 应用层协议是我们程序猿自己定的.。但实际上, 已经有大佬们定义了一些现成的, 又非常好用的应用层协议, 供我们直接参考使用. HTTP(超文本传输协议)就是其中之一。
下面我们看个常见的url:

在这里插入图片描述

  • http://是URL的协议部分,这代表网页使用的是HTTP协议
  • 服务器地址:也就是域名部分,还可以用IP地址作为域名使用
  • 服务器端口号:http使用的是80,https使用的是443端口号,它可以省略。因为有的端口号已经被内定了。就像生活中的119,110这些电话,我们一看到就知道是火警和报警电话。有的协议和端口号已经是强绑定的,我们绑定不了。
  • 域名/:这个斜杠是url资源所处的路径,在Linux中一切接文件,这个路径存放着图片啊、视频啊…
  • 查询字符串:是这次http请求的参数。是客户端与服务器之间传递数据的一种方式,多个参数之间用&连接
  • 片段标识符:表示要跳转到本页面的某一部分

urlencode和urldecode

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

转义的规则如下:

将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。例如:输入C++
在这里插入图片描述
+被转移成了%2B了,urldecode就是urlencode的逆过程。

urlencode工具(https://tool.chinaz.com/Tools/urlencode.aspx)

http协议格式

http请求

在这里插入图片描述

注意:

  • 所以当服务器读客户端的请求时是一行一行读的,当读到空行时,再往下读就是正文部分了。
  • 当服务器收到多个请求时怎么保证不会读到其他请求的正文呢?在请求报头中有个content-Length,它会标识每个正文有多少字节,保证不会读到多余的正文。
  • 请求报头由多个key-value组成

抓包

下面来用fildder抓包工具来抓下包试试:比如我抓个nba的
在这里插入图片描述
在这里插入图片描述

看圈起来的raw

在这里插入图片描述

  • 由于我是粘贴在画图板的,fildder中是一行一行的,这就是hppt请求的结构
  • 请求报头中有key:value组成的一些属性
  • 空行下面是正文,请求报头中有connet-Lenght是320.说明正文有320个字节,正文是fildder编码的问题不要在意

http响应

我们再来看看响应请求
在这里插入图片描述

再来看看对应的刚刚抓的包

在这里插入图片描述

  • 响应行有http的版本状态码状态码描述
  • 响应报头: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
  • 如果有正文则content-Length描述正文有多少字节

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
TRCAE 追踪路径 1.1
CONNECT 要求用隧道协议连接代理 1.1
LINK 建立和资源之间的联系 1.0
UNLINE 断开的连接关系 1.0

我们常用的2中方法是GET和POST

  • GET 通过url来传参,长度限制
  • POST是通过正文来传参

http的状态码

类别 原因短语
1XX Informantion(信息性状态码) 接收的请求正在处理
2XX Sucess (成功状态码) 请求正常处理完毕
3XX Redirection(重定向状态码) 需要进行附加操作已完成请求
4XX Clinet Error(客户端错误状态码) 服务器无法处理请求
5XX Server Error(服务器状态码) 服务器处理请求出错

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

  • 程序员最想看到的:200-OK。
  • 程序员不想看到的:500-Internal-Server-Error。
  • 用户不想看到的:401-Unauthorized、403-Forbidden、408-Request-Time-out

http常见的Header

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

http是无状态的,不会记录用户的信息,则会导致用户需要一直登录,用户的体验很差。我们平时只要登录一次下次就用登录是怎么回事呢?是因为Cookie是有状态的。

在这里插入图片描述
客户端自一次发送请求将自己的用户名和密码发送给服务器,服务器会创建set_cookie文件,再发送回客户端的浏览器,cookie文件则保存在浏览器中。cookie的本质就是浏览器中的一个文件

如下面的例子:
在这里插入图片描述

有一天电脑中病毒了,cookie文件被盗了,我们和服务器的通信细节都会被别人知道了,那该怎么办呢?就要用session来处理了。

在这里插入图片描述

session是将敏感的信息放在服务器中,返回给客户端一个cookie sid,下次客户端返送请求,服务器通过sid找到之前的状态。注意session是相对安全一些。

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

https

https比http多了加密和解密,http是直接将数据交给下一层,https是先交给SSL/TLS进行加密。

在这里插入图片描述

对称加密

对称加密用一把秘钥进行加密和解密。
在这里插入图片描述
这样的通信不安全,秘钥丢了就吉吉了。

非对称加密

非对称加密通常公钥加密私钥解密

在这里插入图片描述

具体流程:

  • 首先客户端和服务器协商用什么加密算法,服务器说用非对称,把公钥发给客户端
  • 客户端得到公钥,来加密对称加密的私钥,服务器通过秘钥解密得到秘钥
  • 双方可以使用对称加密进行通信

为什么不直接用非对称加密通信?

非对称加密效率低,对称加密效率高。

实现一个简单的http服务器

实现一个简单的http服务器,在网页上输出hello

httpServer.hpp

  1 #include<iostream>                                                                                                                  
  2 #include<sys/socket.h>
  3 #include<sys/types.h>
  4 #include<arpa/inet.h>
  5 #include<netinet/in.h>
  6 #include<unistd.h>
  7 #include<signal.h>
  8 #define BACKLOG 5
  9 using namespace std;
 10 
 11 class httpServer
 12 {
 13 
 14   private:
 15     int port;
 16     int lsock;
 17   public:
 18     httpServer(int _port=8080,int _lsock= -1)
 19     :port(_port)
 20      ,lsock(_lsock)
 21     {}
 22    void initServer()
 23    {
 24      signal(SIGCHLD,SIG_IGN);
 25       lsock=socket(AF_INET,SOCK_STREAM,0);
 26       if(lsock < 0)
 27       {
 28         cerr<<"socket error"<<endl;
 29         exit(2);
 30       }
 31       struct sockaddr_in local;
 32       local.sin_family = AF_INET;
 33       local.sin_port = htons(port);
 34       local.sin_addr.s_addr = INADDR_ANY;
 35       if(bind(lsock,(struct sockaddr*)&local,sizeof(local)) < 0)
 36       {
 37         cerr<<"bind error"<<endl;
 38         exit(3);      
 39       }
 40       if(listen(lsock,BACKLOG) < 0)
 41       {
 42         cerr<<"listen error"<<endl;
 43         exit(4);
 44       }
 45 
 46    }
 47    void EchoHttp(int sock)
 48    {
 49       char response[2048];
 50       ssize_t s = recv(sock,response,sizeof(response),0);
 51       if(s > 0)
 52       {
 53           response[s] = 0;
 54           string response = "HTTP/1.0 200 OK\r\n";
 55           response += "Content-type: text/html\r\n";
 56              
 57           response += "\r\n";
 58 
 59           response += "<html><h1>hello </h1></html>";
 60         send(sock,response.c_str(),response.size(),0);
 61 
 62    }
 63       close(sock);
 64  }
 65    void start()                                                                                                                     
 66    {
 67      struct sockaddr_in peer;
 68      for(;;){
 69      socklen_t len = sizeof(peer);
 70       int sock = accept(lsock,(struct sockaddr*)&peer,&len);
 37         cerr<<"bind error"<<endl;
 38         exit(3);      
 39       }
 40       if(listen(lsock,BACKLOG) < 0)
 41       {
 42         cerr<<"listen error"<<endl;
 43         exit(4);
 44       }
 45 
 46    }
 47    void EchoHttp(int sock)
 48    {
 49       char response[2048];
 50       ssize_t s = recv(sock,response,sizeof(response),0);
 51       if(s > 0)
 52       {
 53           response[s] = 0;
 54           string response = "HTTP/1.0 200 OK\r\n";
 55           response += "Content-type: text/html\r\n";
 56              
 57           response += "\r\n";
 58 
 59           response += "<html><h1>hello </h1></html>";
 60         send(sock,response.c_str(),response.size(),0);
 61 
 62    }
 63       close(sock);
 64  }
 65    void start()                                                                                                                     
 66    {
 67      struct sockaddr_in peer;
 68      for(;;){
 69      socklen_t len = sizeof(peer);
 70       int sock = accept(lsock,(struct sockaddr*)&peer,&len);
 71       if(sock < 0)
 72       {
 73         cerr<<"accept error"<<endl;
 74         continue;
 75       }
 76      if(fork() == 0)
 77      {
 78        close(lsock);
 79        EchoHttp(sock);
 80        exit(0);
 81      }
 82      close(sock);
 83    }
 84 }
 85     ~httpServer()
 86     {
 87       if(lsock != -1)
 88       {
 89         close(lsock);
 90       }
 91     }
 92 };                               

httpServer.cc

  1 #include "httpServer.hpp"
  2 
  3 static void Usage(string proc)
  4 {
  5    cout << "Usage:\n\t";
  6   cout << proc << " port" << endl;
  7 
  8 }
  9 
 10 int main(int argc ,char *argv[])
 11 {
 12   if(argc != 2){
 13    Usage(argv[0]);
 14    exit(1);
 15 
 16   }
 17 
 18  httpServer *hp = new httpServer(atoi(argv[1]));
 19    hp->initServer();
 20    hp->start();                                                                                                                     
 21 
 22    return 0;
 23 
 24 }

在浏览器输入ip地址:端口号

在这里插入图片描述
一个简单的http服务器就搞定了。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。