网络协议分析(1):HTTP/HTTPS

HTTP/HTTPS

提示:HTTP是万维网进行数据通信的基础
超文本传输协议(HyperText Transfer Protocol)
是一种用于分布 式、协作式和超媒体信息系统的应用层协议。



前言

本文将从基本原理出发,讲解http与https协议各自的报文结构及特点,并通过python与go进行模拟,最后将点明两者的区别


一、HTTP

HTTP(Hyper Text Transfer Protocol: 超文本传输协议) 是一种简单的请求 - 响应协议,被用于在 Web 浏览器和网站服务器之间传递消息。HTTP 使用 TCP(而不是 UDP)作为它的支撑运输层协议。其默认工作在 TCP 协议 80 端口,HTTP 客户机发起一个与服务器的 TCP 连接,一旦连接建立,浏览器和服务器进程就可以通过套接字接口访问 TCP。客户机从套接字接口发送 HTTP 请求报文和接收 HTTP 响应报文。类似地,服务器也是从套接字接口接收 HTTP 请求报文和发送 HTTP 响应报文。其通信内容以明文的方式发送,不通过任何方式的数据加密。当通信结束时,客户端与服务器关闭连接。

以下是 HTTP 请求/响应的步骤

  1. 客户端连接到Web服务器 ,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接
  2. 通过TCP套接字,客户端向Web服务器发送HTTP请求
  3. Web服务器解析请求,并将客户端所求资源复写到TCP套接字,由客户端接收资源
  4. 若connection 模式为close,服务器在响应请求后主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
  5. 客户端浏览器解析HTML内容

在浏览器地址栏键入URL,按下回车之后会经历以下流程

  1. 浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
  2. 解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP连接;
  3. 浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;
  4. 服务器对浏览器请求作出响应
  5. 释放 TCP连接;
  6. 浏览器将所接收的HTML内容渲染出来

二、HTTP报文

1.报文解析

HTTP请求报文:

HTTP请求报文由请求行请求头空行请求体这四部分组成

请求行部分:请求方法,请求地址,HTTP版本

请求方法:

1 GET 请求指定的页面信息,并返回实体主体。
2 HEAD 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
3 POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。
4 PUT 从客户端向服务器传送的数据取代指定的文档的内容。
5 DELETE 请求服务器删除指定的页面。
6 CONNECT HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
7 OPTIONS 允许客户端查看服务器的性能。
8 TRACE 回显服务器收到的请求,主要用于测试或诊断。
9 PATCH 是对 PUT 方法的补充,用来对已知资源进行局部更新 。

提示:请求方法的介绍来自于菜鸟教程[(https://www.runoob.com/http/http-methods.html)]

请求头部分:
】自己总结的http请求头
空行:平平无奇的换行符

请求正文:普普通通的正文内容(对所请求的资源进行描述)

HTTP响应报文:

HTTP响应报文由状态行响应头空行响应体这四部分组成

状态行:版本号(HTTP/1.1)、响应状态码(200)、响应状态码描述(OK)

响应头:
自己总结的http响应头
空行:平平无奇的换行符

请求正文:普普通通的正文内容(响应数据)

2.模拟报文

python代码如下(示例):
使用socket库去发起TCP套接字连接,并在构建好报文后发送报文
使用re解析响应报文,使用pprint美化输出

import socket
import re
import pprint
 
def main():
    # 创建TCP套接字
    tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 连接服务器
    tcp_socket.connect(('www.baidu.com', 80))
 
    # 构建请求报文
    # 请求行
    request_line = 'GET / HTTP/1.1\r\n'
    # 请求头
    request_headers = 'Host:www.baidu.com\r\n'
    # 报文数据
    request_data = request_line + request_headers + '\r\n'

    # 发送请求报文数据
    tcp_socket.send(request_data.encode('utf-8'))

#------------------------------------------------------------------#


    # 接收响应报文数据
    response_data = tcp_socket.recv(10240)
    response_data = response_data.decode()

    # 解析响应报文
    reslult = re.findall(r'\r\n\r\n(.*)', response_data, re.S)
    reslult = response_data.split('\r\n\r\n')[1]
    # 输出响应数据
    pprint.pprint(reslult)
 
    # 关闭套接字
    tcp_socket.close()
 
 
if __name__ == '__main__':
    main()

美化后的输出
提示:水平有限,代码比较简陋,也不知道怎么详细讲解,刚入门的小伙伴暂时先看备注吧,有问题还请不吝留言

我也是刚开始学习go语言,所以不太熟练,就参照网上的代码进行了改写
不同于python代码的构建并发送报文,而是直接监听socket,通过返回数据可以看出报文结构:请求行,请求头,空行

package main

import (
    "fmt"
    "log"
    "net"
)

func main() {
    //连接、监听socket
    listenner, err := net.Listen("tcp", "127.0.0.1:8000")
    if err != nil {
        log.Fatal(err) //log.Fatal()会产生panic
    }

    defer listenner.Close()

    connect, err := listenner.Accept() //阻塞等待客户端连接
    if err != nil {
        log.Println(err)
        return
    }

    defer connect.Close() //此函数结束时,关闭连接套接字

    //conn.RemoteAddr().String():连接客服端的网络地址
    ipAddr := connect.RemoteAddr().String()
    fmt.Println(ipAddr, "连接成功")

    buf := make([]byte, 4096) //缓冲区,用于接收客户端发送的数据

    //阻塞等待用户发送的数据
    n, err := connect.Read(buf) //n代码接收数据的长度
    if err != nil {
        fmt.Println(err)
        return
    }

    //切片截取,只截取有效数据
    result := buf[:n]
    fmt.Printf("接收到数据来自[%s]==>:\n%s\n", ipAddr, string(result))
}

go

三、HTTPS

HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer)是以安全为目标的 HTTP 协议,在 HTTP 的基础上通过传输加密和身份认证的方式保证了传输过程的安全性。其工作流程如下:

① 客户端发起一个 HTTPS 请求,并连接到服务器的 443 端口,发送的信息主要包括自身所支持的算法列表和密钥长度等;

② 服务端将自身所支持的所有加密算法与客户端的算法列表进行对比并选择一种支持的加密算法,然后将它和其它密钥组件一同发送给客户端。

③ 服务器向客户端发送一个包含数字证书的报文,该数字证书中包含证书的颁发机构、过期时间、服务端的公钥等信息。

④ 最后服务端发送一个完成报文通知客户端 SSL 的第一阶段已经协商完成。

⑤ SSL 第一次协商完成后,客户端发送一个回应报文,报文中包含一个客户端生成的随机密码串,称为 pre_master_secre,并且该报文是经过证书中的公钥加密过的。

⑥ 紧接着客户端会发送一个报文提示服务端在此之后的报文是采用pre_master_secre 加密的。

⑦ 客户端向服务端发送一个 finish 报文,这次握手中包含第一次握手至今所有报文的整体校验值,最终协商是否完成取决于服务端能否成功解密。

⑧ 服务端同样发送与第 ⑥ 步中相同作用的报文,已让客户端进行确认,最后发送 finish 报文告诉客户端自己能够正确解密报文。

当服务端和客户端的 finish 报文交换完成之后,SSL 连接就算建立完成了,之后就进行和 HTTP 相同的通信过程,唯一不同的是在 HTTP 通信过程中并不是采用明文传输,而是采用对称加密的方式,其中对称密钥已经在 SSL 的建立过程中协商好了。

1.特点

  • 采用二进制格式而非文本格式;
  • 完全多路复用,而非有序并阻塞的、只需一个连接即可实现并行;
  • 使用报头压缩,降低开销
  • 服务器推送
  • 采用对称加密和非对称加密的混合加密方法

2.区别

  • HTTP 协议以明文方式发送内容,数据都是未加密的,安全性较差。HTTPS 数据传输过程是加密的,安全性较好
  • HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是 80 端口,后者是 443 端口。
  • HTTPS 协议需要到数字认证机构(Certificate Authority, CA)申请证书,一般需要一定的费用。
  • HTTP 页面响应比 HTTPS 快,主要因为 HTTP 使用 3 次握手建立连接,客户端和服务器需要握手 3 次,而 HTTPS 除了 TCP 的 3 次握手,还需要经历一个 SSL 协商过程。

总结

提示:若有错误,请留言指正

总结了一下对HTTP协议和HTTPS协议的笔记,自认为HTTP协议讲解的还是不错的,但是HTTPS讲解过于浅薄(HTTPS的重点应该在加密上,这方面不太懂),如果想深入了解的友友们可以看看我推荐的书目

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值