HTTP静态WEB服务器

HTTP的作用

  • 伯纳斯-李在1989年提出了万维网的基本框架,三个核心概念分别是HTTP协议、URL和HTML。HTTP协议就是浏览器和web服务器之间特定的数据传输格式。
  • HTTP网络协议栈由以下几部分构成,加入安全层的即为HTTPS协议。
    • 物理层:
    • 数据链路层:提供网络结构
    • 网络层:IP
    • 传输层:TCP
    • (安全层:SSL)
    • 应用层:HTTP
  • 与基于TCP的服务器相比,HTTP服务器特殊之处是接受和发送的内容为HTTP报文,HTTP报文由三部分构成,Start line、Header、Body。

面向对象的HTTP静态WEB服务器

import socket, sys, threading

class HttpServer(object):
    '''定义一个HTTP服务器'''
    def __init__(self,port):
        static_web_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        static_web_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 能够通过输入制定端口
        static_web_server.bind(('127.0.0.1', port))
        self.static_web_server = static_web_server

    def start(self):
        # 启动服务器
        self.static_web_server.listen(128)
        while True:
            client_service, client_ip_port = self.static_web_server.accept()
            # 实现多线程并设置守护
            sub_web_thread = threading.Thread(target=HttpServer.supply_service,
                                              args=(client_service,), daemon=True)
            sub_web_thread.start()

    @staticmethod
    def supply_service(client_service):
        recv_data = client_service.recv(4096)
        # 检查客户端提交的请求中是否存在HTTP格式中的资源路径,若无则关闭连接
        try:
            request_path = recv_data.decode('utf-8').split(' ', maxsplit=2)[1]
        except Exception as error:
            client_service.close()
            return
        else:
            # 根目录返回index页面
            if request_path == '/':
                request_path = '/index.html'
            # 根据资源路径制作响应报文并发送
            HttpServer.make_response(request_path, client_service)

    @staticmethod
    def make_response(request_path,client_service):
        # 检查目录下是否存在请求页面,若无返回error页面
        try:
            with open('static' + request_path, 'rb') as f_obj:
                send_data = f_obj.read()
        except Exception as error:
            response_line = 'HTTP/1.1 404 Not Found\r\n'
            response_header = 'Server:PWS/1.0\r\n'
            with open('static/error.html', 'rb') as f_obj:
                response_body = f_obj.read()
        else:
            # 封装成HTTP相应格式
            response_line = 'HTTP/1.1 200 OK\r\n'
            response_header = 'Server:PWS/1.0\r\n'
            response_body = send_data
        finally:
            response = (response_line + response_header + '\r\n').encode('utf-8') + response_body
            client_service.send(response)
            client_service.close()


def main():
    # 获取命令行参数,并判断是否是正确的端口号

    # 判断获取的参数列表是否是两个item(第一个item是文件名),
    if len(sys.argv) != 2:
        print('Please enter like"python web_server 10086"')
        return

    # 判断获取的参数是否是有效的端口号
    if sys.argv[1].isdigit():
        port = int((sys.argv)[1])
        if 1023 < port < 65536:
            web_server = HttpServer(port)
            web_server.start()
        else:
            print('port is invalid.')
            return
    else:
        print('port is invalid.')
        return
# 判断是否是主程序
if __name__ == '__main__':
    main()

在python文件当前命令行输入python web_server 10086,浏览器就能在http://localhost:10086/index.html中访问static文件夹下的页面。

总结

分步骤逐步开发

  • 编写基于TCP的服务器
  • 从请求报文中解析资源路径,并按HTTP报文格式发送响应报文
  • 函数封装、类封装
  • 命令行启动
09-01 05:10