python web开发 网络编程 HTTP协议、Web服务器、WSGI接口

简介: python web开发 网络编程 HTTP协议、Web服务器、WSGI接口

文章目录


1. HTTP协议

2. Web服务器

3. 静态服务器

创建 web_server.py

4. WSGI 接口

4.1 CGI 通用网关接口

4.2 WSGI

4.3 定义 WSGI 接口

4.4 运行 WSGI 服务

learning from 《python web开发从入门到精通》


1. HTTP协议


应用层最主要的协议:HTTP协议(HyperText Transfer Protocol 超文本传输协议)

用户访问网站时,用户浏览器是客户端(向服务器发请求),网站被称为服务器(收到请求,处理后的响应传给客户端),此过程通过 HTTP 协议实现

利用 TCP 在两台计算机(如Web服务器,客户端)之间传输信息,客户端使用 web浏览器发送 HTTP 请求给 web 服务器,服务器发送响应给客户端


2. Web服务器


当在浏览器中输入 url 后:


浏览器请求 DNS 服务器,进行域名解释,获得 站点 IP 地址

发送一个 HTTP Request 请求 给拥有该 IP 的主机

收到服务器返回的 HTTP Response响应,浏览器渲染效果后呈现给用户

Web 服务器工作原理:


建立连接:客户端通过 TCP/IP 协议建立到服务器的 TCP 连接

请求过程:客户端向服务器发送 HTTP协议请求包,请求资源

应答过程:服务器向客户端发送 HTTP协议应答包,如果资源包含动态语言内容,会先进行处理,得到的数据返回客户端,客户端解释 HTML 渲染在屏幕上

关闭连接:断开客户端和服务器

常用请求方法:


GET:请求指定页面

POST:提交数据(表单或者文件等)

HEAD:类似GET,但仅仅获取报头

PUT:取代服务器上的指定文档内容

DELETE:服务器删除指定页面

OPTIONS:允许客户端查看服务器性能

返回状态码:


1**:请求收到,继续处理

2**:成功返回响应

3**:重定向,为了完成请求,必须进一步执行的动作

4**:客户端错误,如语法错误,或者请求无法实现

5**:服务器错误,服务器不能实现一种明显无效的请求

浏览器 按 F12 可以查看相关信息

image.png


3. 静态服务器


  • 纯粹的 HTML 页面被称为 静态页面

例子:创建一个静态服务器,通过该服务器可以访问包含两个静态页面的网站

  • 导航栏的网页 simple_navbar.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用bootstrap框架制作导航栏</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/popper.js/2.9.2/cjs/popper-base.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/js/bootstrap.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-sm navbar-light bg-light">
    <div class="container-fluid">
        <a class="navbar-brand" href="https://michael.blog.csdn.net/">我的导航</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
                aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                <li class="nav-item">
                    <a class="nav-link active" aria-current="page" href="https://michael.blog.csdn.net/">主页</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">链接</a>
                </li>
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
                       data-bs-toggle="dropdown" aria-expanded="false">
                        关于作者
                    </a>
                    <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
                        <li><a class="dropdown-item" href="#">简历</a></li>
                        <li><a class="dropdown-item" href="#">项目</a></li>
                        <li>
                            <hr class="dropdown-divider">
                        </li>
                        <li><a class="dropdown-item" href="contact.html">联系方式</a></li>
                    </ul>
                </li>
                <li class="nav-item">
                    <a class="nav-link disabled">商城</a>
                </li>
            </ul>
            <form class="d-flex">
                <input class="form-control me-2" type="search" placeholder="输入你的关键词" aria-label="Search">
                <button class="btn btn-outline-success" type="submit">站内搜索</button>
            </form>
        </div>
    </div>
</nav>
</body>
</html>
  • contact.html,在上面的基础上,添加一些额外的联系信息
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>联系michael</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/popper.js/2.9.2/cjs/popper-base.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/js/bootstrap.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-sm navbar-light bg-light">
    <div class="container-fluid">
        <a class="navbar-brand" href="https://michael.blog.csdn.net/">我的导航</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
                aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                <li class="nav-item">
                    <a class="nav-link active" aria-current="page" href="https://michael.blog.csdn.net/">主页</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">链接</a>
                </li>
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
                       data-bs-toggle="dropdown" aria-expanded="false">
                        关于作者
                    </a>
                    <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
                        <li><a class="dropdown-item" href="#">简历</a></li>
                        <li><a class="dropdown-item" href="#">项目</a></li>
                        <li>
                            <hr class="dropdown-divider">
                        </li>
                        <li><a class="dropdown-item" href="contact.html">联系方式</a></li>
                    </ul>
                </li>
                <li class="nav-item">
                    <a class="nav-link disabled">商城</a>
                </li>
            </ul>
            <form class="d-flex">
                <input class="form-control me-2" type="search" placeholder="输入你的关键词" aria-label="Search">
                <button class="btn btn-outline-success" type="submit">站内搜索</button>
            </form>
        </div>
    </div>
</nav>
<div class="bs-docs-header" id="content" tabindex="-1">
    <div class="container">
        <h1> 联系michael </h1>
        <div class="lead">
            <address>
                电子邮件:<strong>michael@xxx.com</strong>
                <br>地址:地球村86号
                <br>邮政编码:<strong>xxxxxx</strong>
                <br><abbr title="Phone">联系电话:</abbr> 1234567890
            </address>
        </div>
    </div>
</div>
</body>
</html>

image.png


创建 web_server.py

实现客户端和服务器的 HTTP 通信

注:由于 HTML 里面写了很多下载的 css 文件地址,路径总是报错,最后还是 建议引用 CDN 写法

<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/css/bootstrap.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/popper.js/2.9.2/cjs/popper-base.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.0.2/js/bootstrap.js"></script>
import socket
import re
from multiprocessing import Process  # 多线程
HTML_ROOT_DIR = './'  # 设置静态页面的根目录
class HTTPServer:
    def __init__(self):
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    def start(self):
        self.server_socket.listen(128)  # 最大连接数128
        print("服务器等待客户端连接...")
        while True:
            client_socket, client_addr = self.server_socket.accept()  # 建立客户端连接
            print("[%s, %s]用户连接上了" % client_addr)
            handle_client_process = Process(target=self.handle_client, args=(client_socket,))
            # 实例化线程,第一个参数调用函数 ,第二个参数 传递给前者的参数,元组形式
            handle_client_process.start()  # 开启线程
            client_socket.close()  # 关闭客户端socket
    def handle_client(self, client_socket):
        # 处理客户端请求
        request_data = client_socket.recv(1024)  # 接收客户端请求
        print("request data:", request_data)
        request_lines = request_data.splitlines()  # 按行分割
        for line in request_lines:
            print(line)  # 输出信息
        request_start_line = request_lines[0]  # 获取请求报文
        print("*" * 10)
        print(request_start_line.decode("utf-8"))
        file_name = re.match(r"\w+ +(/[^ ]*) ", request_start_line.decode("utf-8")).group(1)
        # 使用正则表达式,提取请求的文件名,group(1) 列出第一个括号匹配部分
        if file_name == "/":
            file_name = "/simple_navbar.html"
        try:
            # 尝试打开文件
            file = open(HTML_ROOT_DIR + file_name, "rb")
        except IOError:
            # 读取文件失败,返回404
            response_start_line = "HTTP/1.1 404 Not Found\r\n"
            response_headers = "Server: Michael server\r\n"
            response_body = "The file %s is not found! please check again!" % (HTML_ROOT_DIR + file_name)
        else:
            file_data = file.read()
            file.close()
            # 构造响应数据
            response_start_line = "HTTP/1.1 200 OK\r\n"
            response_headers = "Server: Michael server\r\n"
            response_body = file_data.decode("utf-8")
        # 拼接返回数据
        response = response_start_line + response_headers + "\r\n" + response_body
        print("response data:", response)
        client_socket.send(bytes(response, "utf-8"))  # 向客户端发送响应数据
        client_socket.close()  # 关闭客户端连接
    def bind(self, port):
        self.server_socket.bind(("127.0.0.1", port))
def main():
    http_server = HTTPServer()
    http_server.bind(8000)
    http_server.start()
if __name__ == "__main__":
    main()

image.pngimage.png


4. WSGI 接口


上面实现了一个静态服务器,但是现在很少使用,更多的是使用 动态页面,实现交互性


例如,注册登录网站,用户输入数据,web服务器不处理用户数据(不是它的职责),CGI 诞生


4.1 CGI 通用网关接口


Common Gateway Interface 是一段程序,运行在服务器上

web 服务器将请求发送给 CGI 应用程序,再将 CGI 动态生成的 HTML 页面发送回客户端

CGI 局限性:创建完解释器进程,用完就抛弃,大量的请求导致服务器停机


CGI 加强版 FastCGI 出现,其使用 进程/线程池 来处理一连串的请求

减少了 网页服务器 与 CGI 程序之间 交互的开销


4.2 WSGI


在 FastCGI 标准下写异步的 Web 服务不太方便,WSGI (Web Server Gateway Interface 服务器网关接口) 出现

image.png


4.3 定义 WSGI 接口


最简单的web版本 hello world

def applications(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello, Michael!</h1>']


上面函数就是符合 WSGI 标准的一个 HTTP 处理函数


environ :一个所有 HTTP 请求信息的字典对象

start_response:一个发送 HTTP 响应的函数

好处:web 解析 和 应用程序逻辑 分离,可以各自做自己擅长的事


python 内置了 WSGI:wsgiref 模块(它没有考虑运行效率,仅供开发测试)


4.4 运行 WSGI 服务


wsgi_app.py


# wsgi 应用程序
def app(environ, start_response):
    # 响应信息
    start_response('200 OK', [('Content-Type', 'text/html')])
    file_name = environ['PATH_INFO'][1:] or 'simple_navbar.html'
    HTML_ROOT_DIR = './'
    try:
        # 打开文件
        file = open(HTML_ROOT_DIR + file_name, 'rb')
    except IOError:
        # 响应异常
        response_body = "{} not found".format(HTML_ROOT_DIR + file_name)
    else:
        # 读取文件
        file_data = file.read()
        file.close()
        # 构造响应数据
        response_body = file_data.decode('utf-8')
    return [response_body.encode('utf-8')]  # 返回数据
  • wsgi_server.py
# WSGI 服务器
from wsgiref.simple_server import make_server
from wsgi_app import app
# 创建一个服务器,IP地址为空,端口号为8000,处理函数是app
httpd = make_server('', 8000, app)
print('Serving HTTP on port 8000...')
httpd.serve_forever()  # 开始监听HTTP请求

运行 wsgi_server.py ,在浏览器输入 http://127.0.0.1:8000/ 就可以访问网页了

image.png

相关文章
|
25天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
眼疾识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了4种常见的眼疾图像数据集(白内障、糖尿病性视网膜病变、青光眼和正常眼睛) 再使用通过搭建的算法模型对数据集进行训练得到一个识别精度较高的模型,然后保存为为本地h5格式文件。最后使用Django框架搭建了一个Web网页平台可视化操作界面,实现用户上传一张眼疾图片识别其名称。
89 4
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
|
2月前
|
机器学习/深度学习 人工智能 算法
猫狗宠物识别系统Python+TensorFlow+人工智能+深度学习+卷积网络算法
宠物识别系统使用Python和TensorFlow搭建卷积神经网络,基于37种常见猫狗数据集训练高精度模型,并保存为h5格式。通过Django框架搭建Web平台,用户上传宠物图片即可识别其名称,提供便捷的宠物识别服务。
311 55
|
23天前
|
API Python
【02】优雅草央央逆向技术篇之逆向接口协议篇-以小红书为例-python逆向小红书将用户名转换获得为uid-优雅草央千澈
【02】优雅草央央逆向技术篇之逆向接口协议篇-以小红书为例-python逆向小红书将用户名转换获得为uid-优雅草央千澈
|
2月前
|
数据采集 存储 XML
Python爬虫:深入探索1688关键词接口获取之道
在数字化经济中,数据尤其在电商领域的价值日益凸显。1688作为中国领先的B2B平台,其关键词接口对商家至关重要。本文介绍如何通过Python爬虫技术,合法合规地获取1688关键词接口,助力商家洞察市场趋势,优化营销策略。
|
8天前
|
安全 Linux 网络安全
利用Python脚本自动备份网络设备配置
通过本文的介绍,我们了解了如何利用Python脚本自动备份网络设备配置。该脚本使用 `paramiko`库通过SSH连接到设备,获取并保存配置文件。通过定时任务调度,可以实现定期自动备份,确保网络设备配置的安全和可用。希望这些内容能够帮助你在实际工作中实现网络设备的自动化备份。
37 14
|
17天前
|
JSON 安全 中间件
Python Web 框架 FastAPI
FastAPI 是一个现代的 Python Web 框架,专为快速构建 API 和在线应用而设计。它凭借速度、简单性和开发人员友好的特性迅速走红。FastAPI 支持自动文档生成、类型提示、数据验证、异步操作和依赖注入等功能,极大提升了开发效率并减少了错误。安装简单,使用 pip 安装 FastAPI 和 uvicorn 即可开始开发。其优点包括高性能、自动数据验证和身份验证支持,但也存在学习曲线和社区资源相对较少的缺点。
55 15
|
2月前
|
机器学习/深度学习 人工智能 算法
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
宠物识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了37种常见的猫狗宠物种类数据集【'阿比西尼亚猫(Abyssinian)', '孟加拉猫(Bengal)', '暹罗猫(Birman)', '孟买猫(Bombay)', '英国短毛猫(British Shorthair)', '埃及猫(Egyptian Mau)', '缅因猫(Maine Coon)', '波斯猫(Persian)', '布偶猫(Ragdoll)', '俄罗斯蓝猫(Russian Blue)', '暹罗猫(Siamese)', '斯芬克斯猫(Sphynx)', '美国斗牛犬
203 29
【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
|
2月前
|
算法 网络协议 Python
探秘Win11共享文件夹之Python网络通信算法实现
本文探讨了Win11共享文件夹背后的网络通信算法,重点介绍基于TCP的文件传输机制,并提供Python代码示例。Win11共享文件夹利用SMB协议实现局域网内的文件共享,通过TCP协议确保文件传输的完整性和可靠性。服务器端监听客户端连接请求,接收文件请求并分块发送文件内容;客户端则连接服务器、接收数据并保存为本地文件。文中通过Python代码详细展示了这一过程,帮助读者理解并优化文件共享系统。
|
2月前
|
分布式计算 大数据 数据处理
技术评测:MaxCompute MaxFrame——阿里云自研分布式计算框架的Python编程接口
随着大数据和人工智能技术的发展,数据处理的需求日益增长。阿里云推出的MaxCompute MaxFrame(简称“MaxFrame”)是一个专为Python开发者设计的分布式计算框架,它不仅支持Python编程接口,还能直接利用MaxCompute的云原生大数据计算资源和服务。本文将通过一系列最佳实践测评,探讨MaxFrame在分布式Pandas处理以及大语言模型数据处理场景中的表现,并分析其在实际工作中的应用潜力。
93 2
|
2月前
|
数据采集 存储 API
利用Python爬虫获取1688关键词接口全攻略
本文介绍如何使用Python爬虫技术合法合规地获取1688关键词接口数据,包括环境准备、注册1688开发者账号、获取Access Token、构建请求URL、发送API请求、解析HTML及数据处理存储等步骤,强调遵守法律法规和合理使用爬虫技术的重要性。

热门文章

最新文章