Linux从系统到网络|HTTP协议

Linux从系统到网络|HTTP协议
文章图片


http协议

  • 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:
Linux从系统到网络|HTTP协议
文章图片

  • http://是URL的协议部分,这代表网页使用的是HTTP协议
  • 服务器地址:也就是域名部分,还可以用IP地址作为域名使用
  • 服务器端口号:http使用的是80,https使用的是443端口号,它可以省略。因为有的端口号已经被内定了。就像生活中的119,110这些电话,我们一看到就知道是火警和报警电话。有的协议和端口号已经是强绑定的,我们绑定不了。
  • 域名/:这个斜杠是url资源所处的路径,在Linux中一切接文件,这个路径存放着图片啊、视频啊…
  • 查询字符串:是这次http请求的参数。是客户端与服务器之间传递数据的一种方式,多个参数之间用&连接
  • 片段标识符:表示要跳转到本页面的某一部分
urlencode和urldecode
像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现. 比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.
转义的规则如下:
将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。例如:输入C++
Linux从系统到网络|HTTP协议
文章图片

+被转移成了%2B了,urldecode就是urlencode的逆过程。
urlencode工具(https://tool.chinaz.com/Tools/urlencode.aspx)
http协议格式 http请求 Linux从系统到网络|HTTP协议
文章图片

注意:
  • 所以当服务器读客户端的请求时是一行一行读的,当读到空行时,再往下读就是正文部分了。
  • 当服务器收到多个请求时怎么保证不会读到其他请求的正文呢?在请求报头中有个content-Length,它会标识每个正文有多少字节,保证不会读到多余的正文。
  • 请求报头由多个key-value组成
抓包 下面来用fildder抓包工具来抓下包试试:比如我抓个nba的
Linux从系统到网络|HTTP协议
文章图片

Linux从系统到网络|HTTP协议
文章图片

看圈起来的raw
Linux从系统到网络|HTTP协议
文章图片

  • 由于我是粘贴在画图板的,fildder中是一行一行的,这就是hppt请求的结构
  • 请求报头中有key:value组成的一些属性
  • 空行下面是正文,请求报头中有connet-Lenght是320.说明正文有320个字节,正文是fildder编码的问题不要在意
http响应 我们再来看看响应请求
Linux从系统到网络|HTTP协议
文章图片

再来看看对应的刚刚抓的包
Linux从系统到网络|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是有状态的。
【Linux从系统到网络|HTTP协议】Linux从系统到网络|HTTP协议
文章图片

客户端自一次发送请求将自己的用户名和密码发送给服务器,服务器会创建set_cookie文件,再发送回客户端的浏览器,cookie文件则保存在浏览器中。cookie的本质就是浏览器中的一个文件
如下面的例子:
Linux从系统到网络|HTTP协议
文章图片

有一天电脑中病毒了,cookie文件被盗了,我们和服务器的通信细节都会被别人知道了,那该怎么办呢?就要用session来处理了。
Linux从系统到网络|HTTP协议
文章图片

session是将敏感的信息放在服务器中,返回给客户端一个cookie sid,下次客户端返送请求,服务器通过sid找到之前的状态。注意session是相对安全一些。
  • cookie数据存放在客户的浏览器上,session数据放在服务器上。
  • cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,如果主要考虑到安全应当使用session。
  • session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用cookie。将登陆信息等重要信息存放为SESSION; 其他信息如果需要保留,可以放在cookie中.
https
https比http多了加密和解密,http是直接将数据交给下一层,https是先交给SSL/TLS进行加密。
Linux从系统到网络|HTTP协议
文章图片

对称加密
对称加密用一把秘钥进行加密和解密。
Linux从系统到网络|HTTP协议
文章图片

这样的通信不安全,秘钥丢了就吉吉了。
非对称加密
非对称加密通常公钥加密私钥解密
Linux从系统到网络|HTTP协议
文章图片

具体流程:
  • 首先客户端和服务器协商用什么加密算法,服务器说用非对称,把公钥发给客户端
  • 客户端得到公钥,来加密对称加密的私钥,服务器通过秘钥解密得到秘钥
  • 双方可以使用对称加密进行通信
为什么不直接用非对称加密通信?
非对称加密效率低,对称加密效率高。
实现一个简单的http服务器 实现一个简单的http服务器,在网页上输出hello
httpServer.hpp
1 #include 2 #include/socket.h> 3 #include/types.h> 4 #include 5 #include 6 #include 7 #include.h> 8 #define BACKLOG 5 9 using namespace std; 10 11 class httpServer 12 { 13 14private: 15int port; 16int lsock; 17public: 18httpServer(int _port=8080,int _lsock= -1) 19:port(_port) 20,lsock(_lsock) 21{} 22void initServer() 23{ 24signal(SIGCHLD,SIG_IGN); 25lsock=socket(AF_INET,SOCK_STREAM,0); 26if(lsock < 0) 27{ 28cerr<<"socket error"< 0) 52{ 53response[s] = 0; 54string response = "HTTP/1.0 200 OK\r\n"; 55response += "Content-type: text/html\r\n"; 56 57response += "\r\n"; 58 59response += "hello "; 60send(sock,response.c_str(),response.size(),0); 61 62} 63close(sock); 64} 65void start() 66{ 67struct sockaddr_in peer; 68for(; ; ){ 69socklen_t len = sizeof(peer); 70int sock = accept(lsock,(struct sockaddr*)&peer,&len); 37cerr<<"bind error"< 0) 52{ 53response[s] = 0; 54string response = "HTTP/1.0 200 OK\r\n"; 55response += "Content-type: text/html\r\n"; 56 57response += "\r\n"; 58 59response += "hello "; 60send(sock,response.c_str(),response.size(),0); 61 62} 63close(sock); 64} 65void start() 66{ 67struct sockaddr_in peer; 68for(; ; ){ 69socklen_t len = sizeof(peer); 70int sock = accept(lsock,(struct sockaddr*)&peer,&len); 71if(sock < 0) 72{ 73cerr<<"accept error"<

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

在浏览器输入ip地址:端口号
Linux从系统到网络|HTTP协议
文章图片

一个简单的http服务器就搞定了。

    推荐阅读