静态web服务器

一、返回固定页面的静态web服务器

返回固定页面的静态web服务器很容易实现,步骤如下:

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

代码如下:

import socket

# 创建socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置端口复用,程序退出端口立即释放
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口
server_socket.bind(('', 12345))
# 开启监听
server_socket.listen(5)

while True:
    # 等待客户端连接
    server_client_socket, client_addr = server_socket.accept()
    # 接收客户端连接的数据
    recv_data = server_client_socket.recv(4096)
    # 对接收的数据进行解码打印
    print(recv_data.decode('utf-8'))
    # 响应行
    response_line = 'HTTP/1.1 200 OK\r\n'
    # 响应头
    response_header = 'Server: MYWEBSERVER1.0\r\n'
    # html页面
    with open('static/index.html', 'rb') as f:
        resp_data = f.read()
    # 响应体
    response_body = resp_data
    # 拼接响应报文数据
    response_data = (response_line + response_header + '\r\n').encode('utf-8') + response_body
    # 发送给客户端
    server_client_socket.send(response_data)
    # 关闭与客户端连接的套接字
    server_client_socket.close()

运行上述代码,在浏览器输入 http://127.0.0.1:12345/ 即可访问固定的页面。

 

二、返回指定页面的静态web服务器

返回指定页面的静态web服务器也非常简单,只需要在接收到浏览器请求时,获取请求的资源路径,根据资源路径读取指定文件的数据,再将读取的数据组装成响应报文发送给浏览器即可;如果请求的资源不存在,则组装404状态的响应报文发给浏览器。

代码如下:

import socket

def my_server():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口号复用, 程序退出端口立即释放
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 绑定端口
    server_socket.bind(('', 12345))
    # 开启监听
    server_socket.listen(5)

    while True:
        # 等待接收客户端连接请求
        server_client_socket, ipaddr = server_socket.accept()
        # 接收客户端发送的数据(即浏览器发送的请求报文)
        recv_data_content = server_client_socket.recv(4096)
        # 判断是否为空
        if len(recv_data_content) == 0:
            print('关闭连接')
            server_client_socket.close()
            return
        # 请求报文 开始是类似 GET / HTTP/1.1 的请求行
        recv_data = recv_data_content.decode('utf-8')
        # 请求行(GET / HTTP/1.1)在最开始,使用空格进行分割得到列表,列表第二个元素即是资源路径
        request_path = recv_data.split(' ', maxsplit=2)[1]
        # 如果是请求/ ,指定返回首页
        if request_path == '/':
            request_path = '/index.html'
        try:
            with open('static/' + request_path, 'rb') as f:
                # 响应体
                resp_data = f.read()
                # 响应行
                response_line = 'HTTP/1.1 200 OK\r\n'
                # 响应头
                response_header = 'Server: MyWebSERVER 1.0\r\n'
                # 拼接响应报文
                response_data = (response_line + response_header + '\r\n').encode('utf-8') + resp_data
                # 发送响应报文
                server_client_socket.send(response_data)
        # 如果请求的资源不存在
        except Exception as e:
            # 响应行
            response_line = 'HTTP/1.1 404 Not Found\r\n'
            # 响应头
            response_header = 'Server: MyWebSERVER 1.0\r\n'
            # 响应体
            with open('static/error.html', 'rb') as f:
                resp_data = f.read()
            # 拼接响应报文
            response_data = (response_line + response_header + '\r\n').encode('utf-8') + resp_data
            # 发送数据
            server_client_socket.send(response_data)
        finally:
            server_client_socket.close()

if __name__ == '__main__':
    my_server()

上述代码不支持多个客户端同时访问,如果要同时处理多个请求,可使用多进程或多线程。推荐使用多线程。

对上述代码修改如下:

import socket, threading

def my_server(server_client_socket):
    # 接收客户端发送的数据(即浏览器发送的请求报文)
    recv_data_content = server_client_socket.recv(4096)
    # 请求报文 开始是类似 GET / HTTP/1.1 的请求行
    recv_data = recv_data_content.decode('utf-8')
    # 请求行(GET / HTTP/1.1)在最开始,使用空格进行分割得到列表,列表第二个元素即是资源路径
    request_path = recv_data.split(' ', maxsplit=2)[1]
    print(request_path)
    # 如果是请求/ 指定返回首页
    if request_path == '/':
        request_path = '/index.html'
    try:
        with open('static/' + request_path, 'rb') as f:
            # 响应体
            resp_data = f.read()
            # 响应行
            response_line = 'HTTP/1.1 200 OK\r\n'
            # 响应头
            response_header = 'Server: MyWebSERVER 1.0\r\n'
            # 拼接响应报文
            response_data = (response_line + response_header + '\r\n').encode('utf-8') + resp_data
            # 发送响应报文
            server_client_socket.send(response_data)
    # 如果请求的资源不存在
    except Exception as e:
        # 响应行
        response_line = 'HTTP/1.1 404 Not Found\r\n'
        # 响应头
        response_header = 'Server: MyWebSERVER 1.0\r\n'
        # 响应体
        with open('static/error.html', 'rb') as f:
            resp_data = f.read()
        # 拼接响应报文
        response_data = (response_line + response_header + '\r\n').encode('utf-8') + resp_data
        # 发送数据
        server_client_socket.send(response_data)
    finally:
        server_client_socket.close()

if __name__ == '__main__':
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口号复用, 程序退出端口立即释放
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    # 绑定端口
    server_socket.bind(('', 12345))
    # 开启监听
    server_socket.listen(5)
    while True:
        # 等待客户端连接
        server_client_socket, client_addr = server_socket.accept()
        # 客户端连接上服务端时建立子线程
        sub_thread = threading.Thread(target=my_server, args=(server_client_socket,))
        # 设置守护线程
        sub_thread.daemon = True
        # 开始执行子线程的任务,即my_server函数
        sub_thread.start()

运行上述程序,浏览器输入http://127.0.0.1:12345/ 即可访问首页,输入http://127.0.0.1:12345/资源路径 ,如果资源存在,则访问指定的资源,不存在则接收到404状态响应,访问到指定的错误页面。

 

posted on 2023-05-02 11:05  木去  阅读(36)  评论(0)    收藏  举报