【Python高级366】静态Web服务器开发

开发步骤:

①编写一个TCP服务端程序

②获取浏览器发送的HTTP请求报文数据

③读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器。

④HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字。

返回固定页面的静态Web服务器开发

1、编写index.html文件

这里先写好一个index.html文件,内容:

html 复制代码
<h1>Hello, World!</h1>
<p>这是一个简单的静态Web服务器</p>

2、web服务器开发代码

python 复制代码
import socket

if __name__ == '__main__':
    # 1.创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # AF_INET:IPv4, SOCK_STREAM:TCP协议

    # 2.绑定端口
    tcp_server_socket.bind(('127.0.0.1', 8080))  # 绑定端口
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 设置套接字选项,允许地址重用(端口复用)

    # 3.监听
    tcp_server_socket.listen(128)  # 监听

    # 4.等待客户端连接
    while True:
        new_socket, client_addr = tcp_server_socket.accept()  # 等待客户端连接
        print(f"客户端连接成功: {client_addr}")

        # 5.接收客户端发送的HTTP请求报文数据
        content = new_socket.recv(1024).decode('utf-8')  # 接收客户端发送的HTTP请求报文数据
        print(f"HTTP请求报文数据: {content}")
        # 到这里就可以在浏览器访问,这里就能接收到请求报文数据了

        # 6.返回数据给浏览器,这里的数据是index.html文件中的内容
        with open('index.html', 'rb') as file:  # 注意:⭐⭐这里是用rb读取,都进来就是二进制流⭐⭐
            file_data = file.read()

        # 7.组装HTTP响应报文数据:⭐⭐响应行、响应头、空行、响应体⭐⭐
        response_line = "HTTP/1.1 200 OK\r\n"  # 注意:⭐⭐响应行后面要有\r\n用来换行⭐⭐
        response_header = "Server: CZC/1.1\r\nContent-Type: text/html;charset=utf-8\r\n"  # 告诉浏览器返回的数据类型是html,编码是utf-8
        # ⭐⭐组装HTTP响应报文数据,需要以字节流形式发送⭐⭐
        response_data = (response_line + response_header + "\r\n").encode('utf-8') + response_body  # 如果前面是r模式读取,这里就需要用encode('utf-8')转换为字节流

        # 8.发送HTTP响应报文数据
        new_socket.send(response_data)  # 发送HTTP响应报文数据

        # 9.关闭服务于客户端的套接字
        new_socket.close()  # 关闭服务于客户端的套接字

注意:

  • 这里返回的页面数据是index.html文件中的内容,如果想要返回其他页面数据,只需要修改index.html文件中的内容即可。
  • HTTP报文中的响应行、响应头、空行、响应体,需要以字节流形式发送。
  • 读取index.html文件中的内容,需要使用rb模式读取,因为文件中的内容是二进制流。如果使用r模式读取,需要使用encode('utf-8')转换为字节流。
  • HTTP报文的换行是\r\n,而不是\n。

返回指定页面的静态Web服务器开发

为了打开指定页面,这里先多创建几个html文件,比如:index.html、login.html、register.html、404.html、500.html

基本Web服务器:

  • 编写一个TCP服务端程序(七步走)
  • 获取浏览器发送的HTTP请求报文数据
  • 读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器。
  • HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字。
    返回指定页面:
  • 获取用户请求资源路径
  • 根据请求资源路径,读取指定文件的数据
  • 组装指定文件数据的响应报文,发送给浏览器

用户指定页面是写在HTTP请求报文中的请求行中的资源路径,比如:GET /login.html HTTP/1.1

python 复制代码
import socket

if __name__ == '__main__':
    # 1.创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # AF_INET:IPv4, SOCK_STREAM:TCP协议

    # 2.绑定端口
    tcp_server_socket.bind(('127.0.0.1', 8080))  # 绑定端口
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 设置套接字选项,允许地址重用(端口复用)

    # 3.监听
    tcp_server_socket.listen(128)  # 监听

    # 4.等待客户端连接
    while True:
        new_socket, client_addr = tcp_server_socket.accept()  # 等待客户端连接

        # 5.接收客户端发送的HTTP请求报文数据
        client_request_data = new_socket.recv(4096)
        # 注意:新版浏览器都由自动刷新功能(每隔一段时间不操作,浏览器会自动刷新),所以这里需要判断浏览器是否发送了请求报文数据
        if client_request_data:
            # 如果浏览器发送过来了数据,则需要获取浏览器请求的资源路径
            client_request_data = client_request_data.decode('utf-8')  # 把字节流转换为字符串
            # 获取用户请求资源路径 
            request_line = client_request_data.split('\r\n')[0]  # 获取请求行
            request_line_list = request_line.split(' ')  # 把请求行按空格分割成列表
            request_path = request_line_list[1]  # 获取请求资源路径
            print(f"请求资源路径: {request_path}")

            if request_path == '/':  # ⭐如果用户没有指定访问哪个页面,则默认访问首页
                request_path = '/index.html'
            
            # 根据请求资源路径,读取指定文件的数据
            try:
                with open('.' + request_path, 'rb') as file:  
                    file_data = file.read()
            except Exception as e:
                # 如果用户请求的资源路径不存在,则返回404页面
                with open('404.html', 'rb') as file:  # 读取404页面
                    file_data = file.read()

            # 6.组装指定文件数据的响应报文,发送给浏览器
            response_line = "HTTP/1.1 200 OK\r\n"  # 注意:⭐⭐响应行后面要有\r\n用来换行⭐⭐
            response_header = "Server: CZC/1.1\r\nContent-Type: text/html;charset=utf-8\r\n"  # 告诉浏览器返回的数据类型是html,编码是utf-8
            response_data = (response_line + response_header + "\r\n").encode('utf-8') + file_data  # 如果前面是r模式读取,这里就需要用encode('utf-8')转换为字节流

            new_socket.send(response_data)  # 发送HTTP响应报文数据

            # 7.关闭服务于客户端的套接字
            new_socket.close()

注意:

  • 网页标签的的小图标:favicon.ico
  • 当用户没有指定访问哪个页面,会报错,
    • 所以要加容错,默认访问首页
    • 对于不存在的页面,返回自己写的404页面
    • 如果返回的是图片,一定不能加utf-8编码,否则会乱码,因为图片是二进制流,不需要编码
相关推荐
MaiTube&Maipdf14 分钟前
对外发PDF设置打开次数
运维·服务器·网络
m0_7482359531 分钟前
Python毕业设计选题:基于Hadoop 的国产电影数据分析与可视化_django+spider
hadoop·python·课程设计
岁月如歌,青春不败39 分钟前
R语言森林生态系统结构、功能与稳定性分析与可视化
开发语言·人工智能·python·深度学习·r语言
lory代码搬运工40 分钟前
解决PDF.js部署到IIS服务器上后报错mjs,.ftl 404 (Not Found)
运维·服务器·pdf
赵谨言41 分钟前
基于 Python 考研历年国家分数线大数据分析设计与实现
经验分享·python·毕业设计
云云3211 小时前
云手机:Instagram 账号管理新机遇
服务器·线性代数·安全·智能手机·矩阵
hvinsion1 小时前
Python PDF批量加密工具
android·python·pdf
工业互联网专业1 小时前
Python大数据可视化:基于Python对B站热门视频的数据分析与研究_flask+hive+spider
hive·python·数据分析·flask·毕业设计·源码·spider
萧大侠jdeps2 小时前
Vue 3 与 Tauri 集成开发跨端APP
前端·javascript·vue.js·tauri
爱写代码的小白.2 小时前
RustDesk内置ID服务器,Key教程
linux·运维·服务器