目录
1.HTTP协议
1.1 http介绍
http协议,超文本传输协议
-
超文本: 超越文本,不仅仅是文本,音频、视频、图片、超链接
http协议:最开始设计出来是为了传输网页数据的,但是随着互联网的发展,现在可以传输任意类型的数据。
http协议基础 TCP协议,在进行使用http协议去发送数据的时候,要先建立连接。
http协议规定了浏览器和服务器在进行传输数据的时候的数据的格式。
1.2浏览器和服务器的通信过程
1.通过DNS(域名解析服务器)将域名解析成IP地址
2.浏览器获取到IP地址
3.浏览器和服务器建立连接
4.浏览器向服务器发送http请求数据
5.web服务器程序通过端口根据请求向服务器主机获取资源
6.服务器主机返回资源给web服务器
7.web服务器程序返回http响应数据给浏览器
拓展:
https协议
http+ssl安全套接字层
在发送数据的时候会对数据进行加密,相对的安全,默认端口是443
http协议
默认端口是80
以明文的方式直接发送数据
1.3 url
url 统一资源定位符,(不同的网址访问不同的网页,网页数据资源,访问一个网页,请求这个网页的资源,想要在服务器中能到找到我们想要的网页数据,就需要使用网址,根据网址就可以从服务器中找到对应的资源数据)俗称的 网址
url组成
例子:https://v.qq.com/x/cover/mzc00200t096vns/d00431pskow.html
协议部分
http
https等
域名部分
v.qq.com
域名就是IP地址的别名
它是用点进行分割使用英文字母和数字组成的名字,使用域名的目的就是方便记住某台主机IP地址
资源路径
/x/cover/mzc00200t096vns/d00431pskow.html
路径参数
查询参数
表现形式:
?key = value&key1 = value1,表示服务器传递数据的时候
参数说明:?后面的表示第一个参数,后面的参数都使用&进行连接
1.4 请求报文
请求报文指的是,浏览器给服务器发送请求的时候的数据格式。属于http协议规定好的数据格式
请求报文的分类
-
GET请求的请求报文
-
POST请求的请求报文
在浏览器发送请求的时候,常见的有两种请求方式,一种是 get,一种是post。
-
get 请求,在浏览器地址栏中能够看到的url地址的请求,就是get请求,一般用于去获取服务器数据。 (读取),get请求也可以向服务器发送数据,但是数据都会显示在浏览器地址栏中。
-
post请求,在浏览器地址栏中看不到,隐藏在浏览器开发者工具中Network中, 一般网站中用于去向服务器提交数据,常见的 登录 注册 都是使用 post来实现的。 因为向服务器发送的数据会被隐藏起来,会比get请求要安全。
GET请求报文
浏览器在发送请求的时候,自动给我们生成的,我们自己是不需要去写的。
-
请求行: ==请求方式
空格
请求的资源路径空格
http协议的版本\r\n== -
请求头:
key:value 类似于字典
-
空行: 空行可以使用
\r\n
表示, 在浏览器中看不到 -
GET / HTTP/1.1\r\n Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n 表示页面可以支持的类型 Accept-Encoding: gzip, deflate, br 表示页面在传输的时候压缩格式 Accept-Language: zh-CN,zh;q=0.9\r\n 页面支持的语言 Cache-Control: no-cache\r\n 缓存控制 Connection: keep-alive\r\n 连接类型 Cookie: BIDUPSID=F183DF347890B82E5EAC14C44AE3A1DC; PSTM=1660203797;\r\n 记录用户登录状态 Host: www.baidu.com\r\n 域名 Pragma: no-cache\r\n 参数 Upgrade-Insecure-Requests: 1\r\n 升级不安全的请求 为1表示进行升级 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36\r\n 用户代理,用户浏览器的身份标识(浏览器的身份证) \r\n
post请求报文
-
请求行
-
请求头
-
空行
-
请求体: 格式: key:value 放的数据是 浏览器向服务器发送的数据
2.5响应报文
服务器向浏览器响应数据的数据的时候,数据格式
组成
-
响应行: 协议版本空格响应状态码空格状态码的描述信息\r\n
-
响应头: 格式
key:value
响应头的信息一般我们不需要关注 -
空行:
\r\n
-
响应体(响应数据): 服务器返回给浏览器的数据。
HTTP/1.1 200 OK\r\n 响应行
Bdpagetype: 1
Bdqid: 0xf52c1c3e00002995
Cache-Control: private
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html;charset=utf-8
Date: Tue, 30 Aug 2022 03:17:49 GMT
Expires: Tue, 30 Aug 2022 03:17:04 GMT
Server: BWS/1.1
Set-Cookie: BDSVRTM=0; path=/
Set-Cookie: BD_HOME=1; path=/
Set-Cookie: H_PS_PSSID=36552_36626_36977_36885_34813_37268_36570_37077_26350_37204_37233; path=/; domain=.baidu.com
Strict-Transport-Security: max-age=172800
Traceid: 1661829469060108877817666526490881173909
X-Frame-Options: sameorigin
X-Ua-Compatible: IE=Edge,chrome=1
Transfer-Encoding: chunked
2.6响应状态码
响应状态码用于去描述。浏览器发送请求之后,状态,(成功\失败\xxx) 状态码是有三位数字组成
-
2xx: 表示请求成功
-
200
-
-
3xx: 表示重定向(本来请求A网页的,点击之后,跳转到B网页)
-
302
-
307
-
-
4xx: 一般表示服务器资源不存在。
-
404 找不到
-
403 forbidden 权限被拒绝,没有权限访问某个页面
-
-
5xx: 一般指的是服务器的的错误(服务器里面代码出bug了、服务器里面的数据库挂掉了)
-
500 服务器内部又问题
-
503 爬虫用户,在同一之间内。访问的用户量特别大,造成服务器没有办法及时响应,返回503
-
3.web服务器开发
3.1基本的web服务器开发
import socket
# 开发一个web服务器和开发一个TCP服务器的步骤基本一样
# 1. 创建socket对象
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 绑定端口号
tcp_server_socket.bind(("", 8080))
# 3. 设置监听
tcp_server_socket.listen(128)
# 4. 等待客户端连接
client_socket, ip_port = tcp_server_socket.accept()
print(f'客户端: {ip_port} 连接成功.......')
# 5. 接收消息
client_data = client_socket.recv(1024)
print(f'接收到客户端的消息为:\n{client_data.decode()}')
# 6. 发送消息 浏览器请求的服务器,发送的数据格式和返回的数据格式都要符合http协议要求的数据格式
# 请求报文(浏览器自动构造好的,我们不需要写) 和 响应报文(服务器返回的数据格式。 需要手动的构造一个响应报文的格式即可)
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头 key:value
response_head = "server: python_serve\r\n"
# 响应体
response_body = "你好呀,客户端"
response_data = response_line + response_head + "\r\n" + response_body
client_socket.send(response_data.encode("gbk"))
# 7. 关闭
client_socket.close()
tcp_server_socket.close()
3.2web服务器-返回固定的网页
import socket
# 开发一个web服务器和开发一个TCP服务器的步骤基本一样
# 1. 创建socket对象
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 绑定端口号
tcp_server_socket.bind(("", 8080))
# 3. 设置监听
tcp_server_socket.listen(128)
while True:
# 4. 等待客户端连接
client_socket, ip_port = tcp_server_socket.accept()
print(f'客户端: {ip_port} 连接成功.......')
# 5. 接收消息
client_data = client_socket.recv(1024)
print(f'接收到客户端的消息为:\n{client_data.decode()}')
# 6. 发送消息 浏览器请求的服务器,发送的数据格式和返回的数据格式都要符合http协议要求的数据格式
# 请求报文(浏览器自动构造好的,我们不需要写) 和 响应报文(服务器返回的数据格式。 需要手动的构造一个响应报文的格式即可)
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头 key:value
response_head = "server: python_serve\r\n"
# 响应体
# 返回给浏览器的数据。
f = open('html/gdp.html', 'r', encoding='utf-8')
response_body = f.read()
f.close()
response_data = response_line + response_head + "\r\n" + response_body
client_socket.send(response_data.encode())
# 7. 关闭
client_socket.close()
# tcp_server_socket.close()
3.3web服务器返回指定网页
mport socket
# 开发一个web服务器和开发一个TCP服务器的步骤基本一样
# 1. 创建socket对象
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 绑定端口号
tcp_server_socket.bind(("", 8080))
# 3. 设置监听
tcp_server_socket.listen(128)
while True:
# 4. 等待客户端连接
client_socket, ip_port = tcp_server_socket.accept()
print(f'客户端: {ip_port} 连接成功.......')
# 5. 接收消息
client_data = client_socket.recv(1024).decode()
# print(f'接收到客户端的消息为:\n{client_data}')
# 6. 发送消息 浏览器请求的服务器,发送的数据格式和返回的数据格式都要符合http协议要求的数据格式
# 请求报文(浏览器自动构造好的,我们不需要写) 和 响应报文(服务器返回的数据格式。 需要手动的构造一个响应报文的格式即可)
# 响应行
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头 key:value
response_head = "server: python_serve\r\n"
# 响应体
# 判断 获取到用户访问文件名, 根据用户访问的文件名读取不同的文件即可
# 用户在浏览器中的请求的资源路径 在 请求报文中的请求行中 可以找到
path = client_data.split(' ')[1]
print(f'请求的资源路径为: {path}')
if path == "/index.html" or path == "/":
# 返回给浏览器的数据。
f = open('html/index.html', 'r', encoding='utf-8')
elif path == "/gdp.html":
f = open('html/gdp.html', 'r', encoding='utf-8')
elif path == "/render.html":
f = open('html/render.html', 'r', encoding='utf-8')
else:
f = open('html/404.html', 'r', encoding='utf-8')
response_body = f.read()
f.close()
response_data = response_line + response_head + "\r\n" + response_body
client_socket.send(response_data.encode())
# 7. 关闭
client_socket.close()
# tcp_server_socket.close()
4.fastapi的使用
fastapi 是 python中的一个web框架,能够帮助我们快速的实现一个web服务器。
fastapi 第三方模块,不是python自带的,想要去使用这个模块,需要先在我们的python解释器中安装上模块。
在python环境中安装第三方模块: pip install 模块名
搭建fastapi环境,需要安装两个模块
pip install fastapi -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install uvicorn -i https://pypi.tuna.tsinghua.edu.cn/simple
# 1. 导包
from fastapi import FastAPI, Response
import uvicorn
# 2. 创建一个fastapi的对象
app = FastAPI()
# 3. 定义函数,一个函数可以理解为就是一个网页。并且这个函数要使用装饰器去装饰(路由装饰器)
# @app.get(在浏览器中请求的资源路径)
@app.get('/index.html')
def index():
# 如果用户在浏览器中请求了 /index.html这个页面,那么就会调用这个函数中的代码
# 打开 index.html 文件,读取里面内容,将内容返回
f = open('html/index.html', 'r', encoding='utf-8')
# 读取文件中的内容
content = f.read()
f.close()
# 构造响应报文 在 fastapi中提供好了, Response 类,我们直接将响应的数据传入到这个类中,即可
# 在这个类中已经将响应报文的格式 封装好了。
return Response(content)
@app.get('/gdp.html')
def gdp():
f = open('html/gdp.html', 'r', encoding='utf-8')
# 读取文件中的内容
content = f.read()
f.close()
# 构造响应报文 在 fastapi中提供好了, Response 类,我们直接将响应的数据传入到这个类中,即可
# 在这个类中已经将响应报文的格式 封装好了。
return Response(content)
@app.get("/render.html")
def render():
f = open('html/render.html', 'r', encoding='utf-8')
# 读取文件中的内容
content = f.read()
f.close()
# 构造响应报文 在 fastapi中提供好了, Response 类,我们直接将响应的数据传入到这个类中,即可
# 在这个类中已经将响应报文的格式 封装好了。
return Response(content)
# 运行服务器 使用 uvicorn模块
uvicorn.run(app, host='192.168.82.169', port=8088)