【详解】静态Web服务器搭建代码实现_Python

2023-11-16

1 浏览器网络请求流程

  1. 浏览器首先链接DNS服务器,获取域名对应的ip地址

  2. 通过ip和http默认端口80链接服务器

  3. 浏览器将请求数据组合成http协议的请求文本,发送给服务端

  4. 服务端收到请求,需要解析请求文本,根据请求资源路径找到对应的资源

  5. 把资源按照http响应格式组成响应文本发送给浏览器

  6. 浏览器收到响应文本之后进行解析展示

    在这里插入图片描述

2 搭建python自带静态web服务器

python -m http.server 
# linux
python3 -m http.server 

-m 运行模块 __name_以__main_

2.1 静态web服务器开发流程

  1. 编写一个TCP服务端程序
  2. 获取浏览器发送的HTTP请求报文数据
  3. 读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器。
  4. HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字。
import socket
import time

if __name__ == '__main__':
    # 1.编写一个TCP服务端程序
    # 创建socekt
    tcp_server_socekt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口复用 
    tcp_server_socekt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 绑定地址
    tcp_server_socekt.bind(("", 8080))
    # 设置监听
    tcp_server_socekt.listen(128)

    while True:
        # 2.获取浏览器发送的HTTP请求报文数据
        # 建立链接 浏览器充当客户端 访问页面 访问服务端
        client_socekt, client_addr = tcp_server_socekt.accept()
        # 获取浏览器的请求信息
        client_request_data = client_socekt.recv(1024).decode()
        print(client_request_data)
    
        # 3.读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
        # with open("./static/index.html", "rb") as f:
        #     file_data = f.read()
        # 二进制读模式
        f = open("./static/index.html", "rb")
        # f = open("./static/favicon.ico", "rb")
        file_data = f.read()
        # 应答行
        response_line = "HTTP/1.1 200 OK\r\n"
        # 应答头
        response_header = "Server:haha\r\n"
        # 应答体
        response_body = file_data
        # 应答数据
        response_data = (response_line + response_header + "\r\n").encode() + response_body
    
        client_socekt.send(response_data)
    
        # 4.HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
        client_socekt.close()

2.2 返回指定页面

解析请求行中的资源路径

# 获取浏览器的请求信息
client_request_data = client_socekt.recv(1024).decode()
if len(client_request_data) <= 1:
   print("客户端已经关闭")
   print(client_request_data)
else:
 # 获取用户请求资源的路径
 request_data = client_request_data.split(" ")
 print(request_data)
 # 求资源的路径
 request_path = request_data[1]

 if request_path == "/":
     request_path = "/index.html"

 # 3.读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
 # 根据请求资源的路径,读取指定文件的数据
 try:
     with open("./static" + request_path, "rb") as f:
         file_data = f.read()
 except Exception as e:
     # 返回404错误数据
     # 应答行
     response_line = "HTTP/1.1 404 Not Found\r\n"
     # 应答头
     response_header = "Server:pwb\r\n"
     # 应答体
     response_body = "404 Not Found sorry"
     # 应答数据
     # 组装指定文件数据的响应报文,发送给浏览器
     response_data = (response_line + response_header + "\r\n" + response_body).encode()

     client_socket.send(response_data)
 else:
     # 应答行
     response_line = "HTTP/1.1 200 OK\r\n"
     # 应答头
     response_header = "Server:pwb\r\n"
     # 应答体
     response_body = file_data
     # 应答数据
     # 组装指定文件数据的响应报文,发送给浏览器
     response_data = (response_line + response_header + "\r\n").encode() + response_body

     client_socket.send(response_data)
 finally:
     # 4.HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
     client_socket.close()

2.3 多任务版服务器

开启多个线程处理接收和发送操作

import socket
import threading

# 获取用户请求资源的路径
# 根据请求资源的路径,读取指定文件的数据
# 组装指定文件数据的响应报文,发送给浏览器
# 判断请求的文件在服务端不存在,组装404状态的响应报文,发送给浏览器

def handle_client_request(client_socekt):
    # 获取浏览器的请求信息
    client_request_data = client_socekt.recv(1024).decode()
    print(client_request_data)
    # 获取用户请求资源的路径
    requst_data = client_request_data.split(" ")
    print(requst_data)

    # 判断客户端是否关闭
    if len(requst_data) == 1:
        client_socekt.close()
        return
    # 求资源的路径
    request_path = requst_data[1]

    if request_path == "/":
        request_path = "/index.html"

    # 3.读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
    # 根据请求资源的路径,读取指定文件的数据
    try:
        with open("./static" + request_path, "rb") as f:
            file_data = f.read()
    except Exception as e:
        # 返回404错误数据
        # 应答行
        response_line = "HTTP/1.1 404 Not Found\r\n"
        # 应答头
        response_header = "Server:pwb\r\n"
        # 应答体
        response_body = "404 Not Found sorry"
        # 应答数据
        # 组装指定文件数据的响应报文,发送给浏览器
        response_data = (response_line + response_header + "\r\n" + response_body).encode()

        client_socekt.send(response_data)
    else:
        # 应答行
        response_line = "HTTP/1.1 200 OK\r\n"
        # 应答头
        response_header = "Server:pwb\r\n"
        # 应答体
        response_body = file_data
        # 应答数据
        # 组装指定文件数据的响应报文,发送给浏览器
        response_data = (response_line + response_header + "\r\n").encode() + response_body

        client_socekt.send(response_data)
    finally:
        # 4.HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
        client_socekt.close()

if __name__ == '__main__':
    # 1.编写一个TCP服务端程序
    # 创建socekt
    tcp_server_socekt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口复用 
    tcp_server_socekt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 绑定地址
    tcp_server_socekt.bind(("", 8080))
    # 设置监听
    tcp_server_socekt.listen(128)

    while True:
        # 2.获取浏览器发送的HTTP请求报文数据
        # 建立链接
        client_socekt, client_addr = tcp_server_socekt.accept()
        # 创建子线程
        sub_thread = threading.Thread(target=handle_client_request, args=(client_socekt,))
        sub_thread.start()

关闭浏览器,服务端报错

原因:客户端关闭,服务端recv方法不会阻塞,一直读取,读取空数据

# 获取浏览器的请求信息
client_request_data = client_socekt.recv(1024).decode()
# 客户端断开连接  需要停止
if not client_request_data:
 return

2.4 面向对象服务端

  1. 定义Server类
  2. 在__init__中创建socket
  3. 定义start开启接收客户端请求
  4. 客户端请求接收到之后开启新线程执行后续的接收和发送数据操作
import socket
import threading

# 获取用户请求资源的路径
# 根据请求资源的路径,读取指定文件的数据
# 组装指定文件数据的响应报文,发送给浏览器
# 判断请求的文件在服务端不存在,组装404状态的响应报文,发送给浏览器
class HttpWebServer:
    def __init__(self):
        # 1.编写一个TCP服务端程序
        # 创建socekt
        self.tcp_server_socekt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 设置端口复用 
        self.tcp_server_socekt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 绑定地址
        self.tcp_server_socekt.bind(("", 8080))
        # 设置监听
        self.tcp_server_socekt.listen(128)

    def handle_client_request(self, client_socekt):
        # while True:
        # 获取浏览器的请求信息
        client_request_data = client_socekt.recv(1024).decode()
        print(client_request_data)
        # 获取用户请求资源的路径
        request_data = client_request_data.split(" ")
        print(request_data)

        # 判断客户端是否关闭
        if len(request_data) == 1:
            client_socekt.close()
            return
        # 求资源的路径
        request_path = request_data[1]

        if request_path == "/":
            request_path = "/index.html"

        # 3.读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
        # 根据请求资源的路径,读取指定文件的数据
        try:
            with open("./static" + request_path, "rb") as f:
                file_data = f.read()
        except Exception as e:
            # 返回404错误数据
            # 应答行
            response_line = "HTTP/1.1 404 Not Found\r\n"
            # 应答头
            response_header = "Server:pwb\r\n"
            # 应答体
            response_body = "404 Not Found sorry"
            # 应答数据
            # 组装指定文件数据的响应报文,发送给浏览器
            response_data = (response_line + response_header + "\r\n" + response_body).encode()

            client_socekt.send(response_data)
        else:
            # 应答行
            response_line = "HTTP/1.1 200 OK\r\n"
            # 应答头
            response_header = "Server:pwb\r\n"
            # 应答体
            response_body = file_data
            # 应答数据
            # 组装指定文件数据的响应报文,发送给浏览器
            response_data = (response_line + response_header + "\r\n").encode() + response_body

            client_socekt.send(response_data)
        finally:
            # 4.HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
            client_socekt.close()

    def start(self):
        while True:
            # 2.获取浏览器发送的HTTP请求报文数据
            # 建立链接
            client_socekt, client_addr = self.tcp_server_socekt.accept()
            # 创建子线程
            sub_thread = threading.Thread(target=self.handle_client_request, args=(client_socekt,))
            sub_thread.start()


if __name__ == '__main__':
    # 创建服务器对象
    my_web_server = HttpWebServer()
    # 启动服务器
    my_web_server.start()

3 动态端口

获取通过命令行执行python文件传递的参数

import sys
# 没有传参数  默认就是模块名
argv = sys.argv
if len(argv)==2 and argv[1].isdigit():
    print(argv[1])

默认没有传递参数,只有一个元素 文件名

 sub_thread.start()

if name == ‘main’:
# 创建服务器对象
my_web_server = HttpWebServer()
# 启动服务器
my_web_server.start()


## 动态端口

获取通过命令行执行python文件传递的参数

```python
import sys
# 没有传参数  默认就是模块名
argv = sys.argv
if len(argv)==2 and argv[1].isdigit():
    print(argv[1])

默认没有传递参数,只有一个元素 文件名

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【详解】静态Web服务器搭建代码实现_Python 的相关文章

随机推荐

  • 如何制作和训练自己的数据集(YoloV5)

    标注方法 1 自己获取的数据集 人工进行标注 全人工 2 自己获取的数据集 首先使用训练好的网络标注一遍 然后手动进行微调 半人工 3 仿真数据集 GAN网络来生成自己的数据集 synthetic data 标注工具 1 CVAT 需要安装
  • undefined 和 undeclared 的区别

    var a undefined b b is not defined 区别 在变量作用域中已经申明但没有赋值的变量 如 a 是undefined 相反 在变量作用域中没有申明过的变量 是undeclared 我们试图访问 undeclare
  • ahook中常用的一些hooks

    官方文档 https ahooks js org zh CN 以下总结一些个人认为非常实用的hook 1 useRequest 请求 import useRequest from ahooks const getSome async gt
  • VUE中使用防抖和节流

    目的 减少请求次数 节省资源 防抖 在事件触发n秒后执行函数 如果在n秒内再次出发 就重新计算 节流 在多次执行某一动作时 限制为每隔一段时间执行一次函数 防抖 连续的事件 只需触发一次 eg 高频率的点击 防止表单重复提交 输入框搜索 输
  • jdk8以上jvm常用参数

    这几天一直在折腾jvm调优的事情 作为新手 把自己遇到的问题记录下来 调整jvm参数的方法有很多 网上也到处是 我也看了很多 选择用tomcat进行jvm参数设置 linux服务器配置 linux系统下的tomcat通过startup sh
  • MySQL优化之索引原理(二)

    一 前言 上一篇内容说到了MySQL存储引擎的相关内容 及数据类型的选择优化 下面再来说说索引的内容 包括对B Tree和B Tree两者的区别 1 1 什么是索引 索引是存储引擎用于快速找到记录的一种数据结构 对性能的提升有很大的帮助 尤
  • 让我来教你如何免费使用RHEL小红帽系统

    RHEL安装注册过程中遇到的问题 从开始注册到正常使用 如何获取正版RHEL 注意事项 VMware虚拟机下载安装 安装中出现的问题 从开始注册到正常使用 答主是个动手能力比较强的人 所以当老师讲到Linux的时候 我就已经掌握了Linux
  • 计算机表格怎么取消分页,Excel表格自动分页、取消分页等技巧 专家详解

    Excel是一款功能强大的软件 利用Excel制作表格时 有时我们需要对表格进行分页打印 那么Excel表格如何自动分页 取消分页呢 下面小编为你带来解答 工具 材料 Excel2010 操作方法 01 打开Excel2010 进入要编辑的
  • 程序包com.sun.xml.internal.messaging.saaj.packaging.mime.util不存在

    添加maven compiler plugin插件即可
  • 区块链技术的应用与发展

    区块链的概念 区块链技术起源于2008年由化名 中本聪 的学者在密码学邮件组发表的奠基性论文 比特币 一种点对点电子现金系统 目前尚没有行业内公认的区块链定义 狭义来讲 区块链是一种按照时间顺序将数据区块以顺序相连的方式组合成的一 种链式数
  • 怎么解决Ubuntu下Hadoop的报错:hadoop:command not found?

    在执行hadoop下的子项目 文字计数功能时出现hadoop command not found 的报错 通过百度以及问老师同学才知道报错的原因是Hadoop的环境变量配置出了问题 解决方案如下 输入命令 sudo vi etc profi
  • 滑动窗口+前缀和-8--LC930.和相同的二元子数组

    class Solution object def numSubarraysWithSum self nums goal type nums List int type goal int rtype int 1 前缀和 presum 0 a
  • RxDownload-基于RxJava打造的下载工具, 支持多线程和断点续传

    http www jcodecraeer com a anzhuokaifa androidkaifa 2016 1104 6743 html 大文件下载测试中 内存占用一直趋于平稳 主要功能 使用Retrofit OKHTTP来进行网络请
  • qt中事件分发器event和事件过滤器eventFilter使用

    在qt中窗口部件接收到主程序的消息映射后 会进入到事件分发器模块 就是event虚函数接口 我们可以在该接口里进行特定事件的自定义处理 而当窗口部件需要过滤某一事件时 可以使用事件过滤器模块 就是eventFilter虚函数接口 它是在进入
  • 阿里云服务上Elasticsearch的安装及简单使用(一)

    Elasticsearch是一个高度可伸缩的开源全文搜索和分析引擎 它允许你以近实时的方式快速存储 搜索和分析大量的数据 它通常被用作基础的技术来赋予应用程序复杂的搜索特性和需求 关于Elasticsearch的一些几本概念 在此不做过多的
  • arduino+ESP32 web配网演示代码

    include
  • 如何查看自己的公网ip

    windos查看公网ip地址 1 直接访问 百度 2 就是win r输入cmd然后输入 tracert www baidu com 3 其他查询地址 https ip cn https ip138 com https ifconfig me
  • 生成对抗网络GANs理解(附代码)

    生成对抗网络GANs理解 附代码 原文地址 http blog csdn net sxf1061926959 article details 54630462 生成模型和判别模型 理解对抗网络 首先要了解生成模型和判别模型 判别模型比较好理
  • jax安装Ubuntu,cudnn版本查看

    Ubuntu18 04 有GPU jax安装后显示错误如图所示 无法识别GPU 使用升级后并不能解决 Cuda gt 11 8 and cudnn gt 8 6 采用如下方法重新安装 pip install jax cuda11 cudnn
  • 【详解】静态Web服务器搭建代码实现_Python

    目录 1 浏览器网络请求流程 2 搭建python自带静态web服务器 2 1 静态web服务器开发流程 2 2 返回指定页面 2 3 多任务版服务器 2 4 面向对象服务端 3 动态端口 1 浏览器网络请求流程 浏览器首先链接DNS服务器