自己的web服务器与自定义的web框架

自定义的web服务器

点击查看代码
import socket
import threading
import sys
import time
import Myframework

class MyHttpWebServer(object):
    def __init__(self,port):
        # 创建http服务器的套接字
        server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        # 设置端口号复用,程序退出之后不需要等待几分钟,直接释放端口
        server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
        server_socket.bind(('',port))
        server_socket.listen(128)
        self.server_socket = server_socket

    # 处理浏览器请求的函数
    @staticmethod
    def handle_browser_request(new_socket):
        # 接受客户端发送过来的数据
        recv_data = new_socket.recv(4096)
        # 如果没有收到数据,那么请求无效,关闭套接字,直接退出
        if len(recv_data) == 0:
            new_socket.close()
            return

        # 对接受的字节数据,转换成字符
        request_data = recv_data.decode('utf-8')
        print('浏览器请求的数据:',request_data)
        request_array = request_data.split(' ',maxsplit=2)
        # 得到请求的路径
        request_path = request_array[1]
        print('请求的路径是:',request_path)

        if request_path == '/': # 如果请求的路径为根目录,自动设置为/index.html
            request_path = '/index.html'

        if request_path.endswith('.html'):
            '''动态资源的请求'''
            # 动态资源的处理交给web框架来处理,需要把请求参数传给web框架,可能会有多个参数,所有采用字典结构
            params = {
                'request_path':request_path
            }
            response = Myframework.handle_request(params)
            new_socket.send(response)
            new_socket.close()

        else:
            '''静态资源的请求'''
            # 其实就是:根据请求路径读取/static目录中静态的文件数据,响应给客户端
            response_first = None  # 响应头的第一行
            response_header = None  # 响应头
            response_body = None # 响应主体

            try:
                # 读取static文件中对应的文件数据,rb模式:是一种兼容模式,可以打开图片,也可以打开js
                with open('static'+request_path,'rb') as f:
                    response_body = f.read()
                response_first = 'HTTP/1.1 200 OK\r\n'
                response_header = 'Server: myserver\r\n'

            except Exception as e: # 浏览器想读取的文件可能不存在
                with open('static/404.html','rb') as f:
                    response_body = f.read()  # 响应的主体页面内容(字节)
                # 响应头
                response_first = 'HTTP/1.1 404 Not Found\r\n'
                response_header = 'Server: myserver\r\n'

            finally: # 不管if和else有没有执行finally最后都会执行
                # 组成响应数据,发送给客户端(浏览器)
                response_data = (response_first + response_header + '\r\n').encode('utf-8') + response_body
                new_socket.send(response_data)
                new_socket.close()  # 关闭套接字

    # 启动服务器,并且接受客户端的请求
    def start(self):
        # 循环并且多线程来接受客户端请求
        while True:
            new_socket,ip_port = self.server_socket.accept()
            print('客户端的ip和端口',ip_port)
            # 一个客户端请求交给一个线程处理
            sub_thread = threading.Thread(target=self.handle_browser_request,args=(new_socket,))
            sub_thread.setDaemon(True)  # 设置当前线程为守护线程
            sub_thread.start()  # 子线程启动

def main():
    web_server = MyHttpWebServer(8080)
    web_server.start()

if __name__ == '__main__':
    main()

自定义的web框架

点击查看代码
import time
from functools import wraps
import pymysql

route_lst = []

# 定义路由装饰器
def route(request_path):  # 参数就是url请求
    def add_route(func):
        # 添加路由到路由表
        route_lst.append((request_path, func))
        @wraps(func)
        def invoke():
            # 调用我们指定的处理函数,并且返回结果
            return func()
        return invoke
    return add_route

# 我们自定义的web框架
def handle_request(params):
    request_path = params['request_path']  # 这里的路径是url上面输入的路径名
    for path, func in route_lst:
        if request_path == path:
            return func()
    else:  # 没有动态资源的数据 返回404
        return page_not_found()
    # 如果是index页面 就返回index页面的数据
    # if request_path == '/index.html':
    #     return index()
    # # 如果是userinfo页面就返回userinfo页面的数据
    # elif request_path == '/userinfo.html':  # request_path是url上面输入的路径名
    #     return user_info()
    # # 如果请求的动态资源没有,就返回404
    # else:
    #     return page_not_found()

# 动态资源页面
@route('/index.html')
def index():
    conn = pymysql.connect(host='localhost', port=3306, user='root', password='root', database='test', charset='utf8')
    cursor = conn.cursor()
    sql = 'select * from t_movies'
    cursor.execute(sql)
    result = cursor.fetchall()
    datas = ''
    for row in result:
        datas += '''<tr>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s 亿人名币</td>
                <td>%s</td>
                <td>%s</td>
                <td>%s</td>
                <td><input type = 'button' value = '删除'/></td>
                </tr>
                ''' % row

    # date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    # response_body = data   # 响应的主体内容
    with open('template/index.html', 'r', encoding='utf-8') as f:
        response_body = f.read()
    response_body = response_body.replace('{%dates%}', datas)
    # 响应头
    response_first = 'HTTP/1.1 200 OK\r\n'
    response_header = 'Server: myserver\r\n'

    response_data = (response_first + response_header + '\r\n' + response_body).encode('utf-8')
    return response_data


# 专门处理user_info.html的动态请求的函数
@route('/userinfo.html')
def user_info():
    date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    # response_body = data   # 响应的主体内容
    with open('template/user_info.html', 'r', encoding='utf-8') as f:  # 这里的user_info.html指的是文件名
        response_body = f.read()
    response_body = response_body.replace('{%dates%}', date)
    # 响应头
    response_first = 'HTTP/1.1 200 OK\r\n'
    response_header = 'Server: myserver\r\n'

    response_data = (response_first + response_header + '\r\n' + response_body).encode('utf-8')
    return response_data


def page_not_found():
    with open('static/404.html', 'rb') as f:
        response_body = f.read()  # 响应的主体页面内容(字节)
    # 响应头
    response_first = 'HTTP/1.1 404 Not Found\r\n'
    response_header = 'Server: myserver\r\n'

    response_data = (response_first + response_header + '\r\n').encode('utf-8') + response_body
    return response_data
posted @ 2021-11-14 14:50  libonizhenshuai  阅读(34)  评论(0)    收藏  举报