HTTP初步学习

HTTP是一种无连接、无状态的应用层协议,HTTP/1.1引入了持久连接和优化,如流水线和分块传输编码。HTTPS通过SSL/TLS握手确保安全,使用非对称加密和会话秘钥保护数据。HTTP方法中,GET是安全幂等的,而POST不是。缓存机制包括If-Modified-Since和ETag策略。
摘要由CSDN通过智能技术生成

HTTP的一个学习记录
包含的知识层次

  • 1.基础

基本概述
网络分层
相关概念

  • 2.http1.0
  • 3.http1.1

基本概述

HTTP(Hypertext Transfer Protocol)是一种用于在客户端和服务器之间进行通信的应用层协议。

以下是HTTP协议的一些关键特点和基本原理:
无连接性(Connectionless):每个HTTP请求都是独立的,服务器在响应后立即关闭连接,不会保持持久连接。这意味着每个请求都需要建立新的连接,增加了一定的开销。为了减少连接建立的开销,引入了持久连接(HTTP/1.1)和连接池等技术。
无状态性(Stateless):HTTP协议本身是无状态的,即服务器不会保留关于客户端的状态信息。每个请求都是相互独立的,服务器不会在不同请求之间保留任何上下文信息。为了处理用户状态,如登录会话等,通常使用会话管理技术,如使用Cookie或Token来维护用户状态。
请求-响应模型:HTTP通信遵循请求-响应模型。客户端发送HTTP请求到服务器,服务器处理请求并返回相应的HTTP响应。请求和响应都由一组结构化的信息组成,包括请求/响应行、请求/响应头和请求/响应体。
URI(Uniform Resource Identifier):URI用于标识要访问的资源,它可以是Web上的一个文件、一个API端点或其他资源。在HTTP请求中,URI用于指定要访问的资源的位置。
请求方法(HTTP Methods):HTTP定义了一组请求方法,用于指定对资源的不同操作。常见的请求方法包括:
GET:获取指定资源的数据。
POST:提交数据,用于创建新资源或处理数据。
PUT:更新指定资源的数据。
DELETE:删除指定资源。
其他方法如PATCH、HEAD、OPTIONS等。
状态码(Status Codes):HTTP响应包括一个状态码,用于指示请求的处理结果。常见的状态码已在前面提到过,例如200表示成功,404表示资源未找到,500表示服务器错误等。
报文格式:HTTP请求和响应都由报文组成,报文包括请求/响应行、请求/响应头和请求/响应体。请求行包含请求方法、URI和HTTP版本;响应行包含状态码和HTTP版本。

相关知识

socket和http 的关系

  • Socket是一种通信机制,而HTTP是一种基于Socket的应用层协议。HTTP使用Socket进行数据的传输,但它还定义了更高级别的概念和规则,例如请求方法、状态码、头部信息等,以便于在Web环境下进行数据交换和资源访问。
  • 客户端通常指的是发起网络请求或连接的一端。
  • 报文:host:服务器地址;accept:接收文件格式;User-agent:代理;Connect:连接状态;

网络分层

分层提供了一种结构化方式来讨论系统组件。模块化使更新系统组件更为容易
同一层是对等实体(服务端和客户端的HTTP是对等实体,TCP也是对等实体),各层的所有协议被称为协议栈(HTTP、TCP等所有分层用到的协议)
-协议模型:osi(七层)和tcp(五层)

  • tcp:(A的ip、端口,B的ip、端口) //B的ip可以是A,即自己连自己
  • 报文:头部+包体
  • time_wait状态

状态码

1xx 类状态码(信息性状态码),指示请求已被接收并继续处理。,是协议处理中的一种中间状态,实际用到的比较少。
2xx 类状态码(成功状态码)表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。
3xx 类状态码(重定向状态码)表示客户端请求的资源发生了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。
4xx 类状态码(客户端错误代码)表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。
5xx 类状态码(服务器错误状态码)表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。如502,503等

问:GET 和 POST 方法都是安全和幂等的吗?

  • 概念:在 HTTP 协议里,所谓的「安全」是指请求方法不会「破坏」服务器上的资源。
    所谓的「幂等」,意思是多次执行相同的操作,结果都是「相同」的。
  • 答:GET 方法就是安全且幂等的,因为它是「只读」操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。所以,可以对 GET 请求的数据做缓存,这个缓存可以做到浏览器本身上(彻底避免浏览器发请求),也可以做到代理上(如nginx),而且在浏览器中 GET 请求可以保存为书签。
    POST 因为是「新增或提交数据」的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不是幂等的。所以,浏览器一般不会缓存 POST 请求,也不能把 POST 请求保存为书签。

协商缓存

第一种请求头部中的 If-Modified-Since 字段与响应头部中的 Last-Modified 字段实现
响应头部中的 Last-Modified:标示这个响应资源的最后修改时间;
请求头部中的 If-Modified-Since:当资源过期(服务器端设置的一个时间戳,用于指示浏览器何时应该重新请求更新资源)了,发现响应头中具有 Last-Modified 声明,则再次发起请求的时候带上 Last-Modified 的时间,服务器收到请求后发现有 If-Modified-Since 则与被请求资源的最后修改时间进行对比(Last-Modified),如果最后修改时间较新(大),说明资源又被改过,则返回最新资源,HTTP 200 OK;如果最后修改时间较旧(小),说明资源无新修改,响应 HTTP 304 走缓存。

第二种请求头部中的 If-None-Match 字段与响应头部中的 ETag 字段
响应头部中 Etag:唯一标识响应资源;
请求头部中的If-None-Match:当资源过期时,浏览器发现响应头里有 Etag,则再次向服务器发起请求时,会将请求头 If-None-Match 值设置为 Etag 的值。服务器收到请求后进行比对,如果资源没有变化返回 304,如果资源变化了返回 200。

对比第一种实现方式是基于时间实现的,第二种实现方式是基于一个唯一标识实现的,相对来说后者可以更加准确地判断文件内容是否被修改,避免由于时间篡改导致的不可靠问题。
如果在第一次请求资源的时候,服务端返回的 HTTP 响应头部同时有 Etag 和 Last-Modified 字段,那么客户端再下一次请求的时候,如果带上了 ETag 和 Last-Modified 字段信息给服务端,这时 Etag 的优先级更高,也就是服务端先会判断 Etag 是否变化了,如果 Etag 有变化就不用在判断 Last-Modified 了,如果 Etag 没有变化,然后再看 Last-Modified。

为什么 ETag 的优先级更高这是因为 ETag 主要能解决 Last-Modified 几个比较难以解决的问题:
在没有修改文件内容情况下文件的最后修改时间可能也会改变,这会导致客户端认为这文件被改动了,从而重新请求;
可能有些文件是在秒级以内修改的,If-Modified-Since 能检查到的粒度是秒级的,使用 Etag就能够保证这种需求下客户端在 1 秒内能刷新多次;
有些服务器不能精确获取文件的最后修改时间。

HTTP/1.1

对比1.0的优势

  • 长连接
  • 早期 HTTP/1.0 性能问题:每发起一个请求,都要新建一次 TCP 连接(三次握手),而且是串行请求,做了无谓的 TCP 连接建立和断开
  • HTTP/1.1 提出了长连接的通信方式,也叫持久连接。这种方式的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。长连接超过一定时间没有任何数据交互,服务端就会主动断开这个连接。
  • 管道网络传输
  • 如果服务端在处理 A 请求时耗时比较长,那么后续的请求的处理都会被阻塞住,这称为「队头堵塞」

对HTTP/1.1的优化

  • 减少重定向请求
  • 重定向请求:所求的资源从url1迁移到url2,客户端使用url1获取页面时,服务器返回url2,然后用户使用url2来获取资源
  • 用户的请求一般先传到代理服务器,再由代理服务器发送到url到源服务器。
    方式:用户url1传到代理服务器,代理服务器用url1得知迁移后,用url2获取资源再返回到用户;如果代理服务器已经知道了迁移到哪里,就在接收到url1后使用url2获取资源返回
  • 合并请求
  • 可以用Css Image Sprites将小图片合并为大图片,减少HTTP请求数量(每个请求都对应tcp连接,合并后只要一个tcp连接)
  • webpack打包的方式,将js、css等文件
  • 延迟发送

当一个页面的URL资源太多的时候,只获取用户看到的资源,当用户向下滑动时再请求资源

  • 压缩文件 使用有损压缩和无损压缩两种方式

持久连接(Persistent Connection):HTTP/1.1引入了持久连接机制,允许在单个TCP连接上发送多个HTTP请求和响应,避免了每次请求都建立和关闭连接的开销,提高了性能和效率。
流水线(Pipeline):HTTP/1.1支持请求和响应的流水线处理,即在发送请求后可以继续发送后续请求,而无需等待前面的响应返回。这样可以减少请求的延迟,提高并发性能。
分块传输编码(Chunked Transfer Encoding):HTTP/1.1引入了分块传输编码,允许将响应数据分成多个块进行传输,而不需要事先知道整个响应的大小。这样可以更早地将部分响应数据发送给客户端,提高响应速度。
缓存控制(Cache Control):HTTP/1.1提供了更强大的缓存机制,包括可缓存性、过期控制、验证等方式,使得客户端和代理服务器可以更有效地利用缓存,减少对服务器的请求,降低网络传输成本。
域名解析优化:HTTP/1.1中可以使用多个域名来并行加载页面的资源,通过将资源分布在不同的域名下,可以增加浏览器同时请求资源的并发数,提高页面加载速度。

这些优化措施可以减少延迟、提高并发性能、节省带宽等,从而提升了HTTP/1.1协议的性能和效率。然而,随着互联网的发展,HTTP/1.1仍存在一些性能瓶颈,后续的HTTP/2和HTTP/3协议进一步对HTTP协议进行了优化和改进。

HTTPS 是如何建立连接的?其间交互了什么?

HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输。默认端口443.
非对称加密算法;一个是公钥,这个是可以公开给所有人的;一个是私钥,这个必须由本人管理,不可泄露。
私钥加密内容不是内容本身,而是对内容的哈希值加密

SSL/TLS 协议基本流程:
客户端向服务器索要并验证服务器的公钥。
双方协商生产「会话秘钥」。
双方采用「会话秘钥」进行加密通信。
前两步也就是 SSL/TLS 的建立过程,也就是 TLS 握手阶段。

TLS 的「握手阶段」涉及四次通信,使用不同的密钥交换算法,TLS 握手流程也会不一样的,现在常用的密钥交换算法有两种:RSA 算法 (opens new window)和 ECDHE 算法 (opens new window)。

HTTPS 的应用数据是如何保证完整性的?

TLS 在实现上分为握手协议和记录协议两层:
TLS 握手协议就是我们前面说的 TLS 四次握手的过程,负责协商加密算法和生成对称密钥,后续用此密钥来保护应用程序数据(即 HTTP 数据);
TLS 记录协议负责保护应用程序数据并验证其完整性和来源,所以对 HTTP 数据加密是使用记录协议;

区块链是一种去中心化的分布式账本技术,它可以用于记录交易、资产、身份验证等信息。在Ubuntu 20.04上学习区块链,可以按照以下步骤进行: 1.安装必要的软件包和依赖项 ```shell sudo apt-get update sudo apt-get install build-essential libssl-dev libffi-dev python3-dev ``` 2.安装Python虚拟环境 ```shell sudo apt-get install python3-venv ``` 3.创建并激活Python虚拟环境 ```shell python3 -m venv blockchain-env source blockchain-env/bin/activate ``` 4.安装区块链相关的Python库 ```shell pip install Flask==1.1.2 requests==2.24.0 ``` 5.创建一个简单的区块链 ```python # blockchain.py import hashlib import json from time import time from uuid import uuid4 from flask import Flask, jsonify, request class Blockchain: def __init__(self): self.chain = [] self.current_transactions = [] # Create the genesis block self.new_block(previous_hash='1', proof=100) def new_block(self, proof, previous_hash=None): """ Create a new Block in the Blockchain :param proof: <int> The proof given by the Proof of Work algorithm :param previous_hash: (Optional) <str> Hash of previous Block :return: <dict> New Block """ block = { 'index': len(self.chain) + 1, 'timestamp': time(), 'transactions': self.current_transactions, 'proof': proof, 'previous_hash': previous_hash or self.hash(self.chain[-1]), } # Reset the current list of transactions self.current_transactions = [] self.chain.append(block) return block def new_transaction(self, sender, recipient, amount): """ Creates a new transaction to go into the next mined Block :param sender: <str> Address of the Sender :param recipient: <str> Address of the Recipient :param amount: <int> Amount :return: <int> The index of the Block that will hold this transaction """ self.current_transactions.append({ 'sender': sender, 'recipient': recipient, 'amount': amount, }) return self.last_block['index'] + 1 @staticmethod def hash(block): """ Creates a SHA-256 hash of a Block :param block: <dict> Block :return: <str> """ # We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes block_string = json.dumps(block, sort_keys=True).encode() return hashlib.sha256(block_string).hexdigest() @property def last_block(self): return self.chain[-1] def proof_of_work(self, last_proof): """ Simple Proof of Work Algorithm: - Find a number p' such that hash(pp') contains leading 4 zeroes, where p is the previous p' - p is the previous proof, and p' is the new proof :param last_proof: <int> :return: <int> """ proof = 0 while self.valid_proof(last_proof, proof) is False: proof += 1 return proof @staticmethod def valid_proof(last_proof, proof): """ Validates the Proof: Does hash(last_proof, proof) contain 4 leading zeroes? :param last_proof: <int> Previous Proof :param proof: <int> Current Proof :return: <bool> True if correct, False if not. """ guess = f'{last_proof}{proof}'.encode() guess_hash = hashlib.sha256(guess).hexdigest() return guess_hash[:4] == "0000" # Instantiate our Node app = Flask(__name__) # Generate a globally unique address for this node node_identifier = str(uuid4()).replace('-', '') # Instantiate the Blockchain blockchain = Blockchain() @app.route('/mine', methods=['GET']) def mine(): # We run the proof of work algorithm to get the next proof... last_block = blockchain.last_block last_proof = last_block['proof'] proof = blockchain.proof_of_work(last_proof) # We must receive a reward for finding the proof. # The sender is "0" to signify that this node has mined a new coin. blockchain.new_transaction( sender="0", recipient=node_identifier, amount=1, ) # Forge the new Block by adding it to the chain previous_hash = blockchain.hash(last_block) block = blockchain.new_block(proof, previous_hash) response = { 'message': "New Block Forged", 'index': block['index'], 'transactions': block['transactions'], 'proof': block['proof'], 'previous_hash': block['previous_hash'], } return jsonify(response), 200 @app.route('/transactions/new', methods=['POST']) def new_transaction(): values = request.get_json() # Check that the required fields are in the POST'ed data required = ['sender', 'recipient', 'amount'] if not all(k in values for k in required): return 'Missing values', 400 # Create a new Transaction index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount']) response = {'message': f'Transaction will be added to Block {index}'} return jsonify(response), 201 @app.route('/chain', methods=['GET']) def full_chain(): response = { 'chain': blockchain.chain, 'length': len(blockchain.chain), } return jsonify(response), 200 if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) ``` 6.运行区块链应用程序 ```shell export FLASK_APP=blockchain.py flask run --port 5000 ``` 现在,您可以使用Postman或类似的工具向http://localhost:5000/transactions/new发送POST请求来创建新的交易,向http://localhost:5000/mine发送GET请求来挖掘新的区块,并向http://localhost:5000/chain发送GET请求来获取整个区块链。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值