博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python实现web动态服务器
阅读量:7209 次
发布时间:2019-06-29

本文共 9261 字,大约阅读时间需要 30 分钟。

 Python实现http动态服务器,有两种方法,一种是基本的实现方式,可扩展性差,但是是实现服务器的基础,第二种实现不修改服务器和架构代码而确保可以在多个架构下运行web服务器。都使用WSGI(Web Server Gateway Interface)。

1.第一种。说明:通过类的方式,实现功能,但是架构代码和服务器没有分离。有两个文件分别是HttpServer.py主文件,以及wsgi_python_program文件夹     下的hello.py

HttpServer.py:

import socketimport reimport sysfrom multiprocessing import ProcessPORT = 8080sys.path.insert(1, "./wsgi_python_program")# 用户能够获取的网页数据存放目录HTML_ROOT_DIR = "./html"class HttpServer(object):    def __init__(self):        self.listen_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        self.listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)    def bind(self, port):        address = ("", port)        self.listen_sock.bind(address)        self.listen_sock.listen(128)    def start(self):        while True:            client_sock, client_addr = self.listen_sock.accept()            print("客户端%s已连接" % (client_addr,))            p = Process(target=self.handle_client, args=(client_sock, client_addr))            p.start()            # 释放client_sock            client_sock.close()    def start_response(self, status_code, response_headers):        """       用来接收响应状态码与响应头       :param status_code:  "200 OK" 状态码       :param response_headers: [("Server", "MyServer"), ("Content-Type", "text")]  响应头       :return: None       """        resp_start_line = "HTTP/1.0 " + status_code + "\r\n"  # 起始行        # 遍历处理response_headers,形成响应头        resp_headers = ""        for header_name, header_value in response_headers:            resp_headers += (header_name + ": " + header_value + "\r\n")        # 将拼接好的响应报文前半部分保存        self.resp_start_line_headers = resp_start_line + resp_headers    def handle_client(self, c_sock, c_addr):        """        子进程处理客户端        :param c_sock:  socket类型对象  处理客户端通信用到的socket对象        :param c_addr:  元组 (ip, port)  客户端的地址信息        :return: None        """        # 接收客户端发送过来的请求数据, 即http请求报文数据        http_req_data = c_sock.recv(1024)        print("客户端 %s 发送的HTTP请求报文:\n %s" % (c_addr, http_req_data.decode()))        # 解析客户端的请求报文        http_req_data_str = http_req_data.decode()        # 对http_req_data_str按照"\r\n"分隔符进行拆分        req_start_line = http_req_data_str.split("\r\n")[0]  # 请求的起始行        # 使用正则表达是从起始行中提出请求的文件名        # GET /index.html HTTP/1.1        match_result = re.match(r"(\w+) +(/\S*) +", req_start_line)        req_method = match_result.group(1)        file_path = match_result.group(2)        print("file_path:", file_path)        # 构造一个字典,用来保存解析的数据        environ = {            "PATH_INFO": file_path,            "REQUEST_METHOD": req_method        }        # 如果用户的请求的是/主路径,返回主页信息        if file_path.endswith(".py"):            file_path = file_path[1:-3]            mod = __import__(file_path)            response_body = mod.application(environ, self.start_response)            resp_data = self.resp_start_line_headers + "\r\n" + response_body            c_sock.send(resp_data.encode())        else:            if file_path == "/":                file_path = "/index.html"            # 打开文件            # file_path = "/index.html"            try:                file = open(HTML_ROOT_DIR + file_path, "rb")            except IOError:                # 表示用户请求的文件不存在,要返回404响应报文                # 构造响应报文                resp_start_line = "HTTP/1.0 404 Not Found\r\n"  # 响应起始行                resp_headers = "Server: MyServer\r\n"  # 响应头                resp_headers += "Content-Type: text\r\n"                resp_body = "file not exist"  # 响应体                http_resp_data = resp_start_line + resp_headers + "\r\n" + resp_body                print("传回给客户端的响应HTTP报文:\n %s" % http_resp_data)                # 传回给客户端响应数据                c_sock.send(http_resp_data.encode())            else:                # 表示请求的文件存在,                # 读取文件内容, bytes类型                file_data = file.read()                # 关闭文件                file.close()                # 构造响应报文                resp_start_line = "HTTP/1.0 200 OK\r\n"  # 响应起始行                resp_headers = "Server: MyServer\r\n"  # 响应头                resp_headers += "Content-Type: text/html\r\n"                http_resp_data = (resp_start_line + resp_headers + "\r\n").encode() + file_data                # 传回给客户端响应数据                c_sock.send(http_resp_data)        # 关闭socket        c_sock.close()def main():    http_server = HttpServer()    http_server.bind(PORT)    http_server.start()if __name__ == '__main__':    main()

wsgi_python_program文件夹下的hello.py

import timedef application(environ, start_response):    status_code = "200 OK"    response_headers = ([("Server", "MyServer"), ("Content-Type", "text/html")])    start_response(status_code, response_headers)    return time.ctime()

 

2.第二种。说明:有三个文件,分别是MyHttpServer文件,即HttpServer服务器主文件,MyFramework.py文件,封装成一个简单的框架。

   urls是请求的地址路由列表,可以添加多个。实现服务器和架构代码分离。

MyHttpServer.py文件

import socketimport refrom multiprocessing import Processimport MyFrameworkPORT = 9000class HttpServer(object):    def __init__(self, app):        self.listen_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        self.listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)        self.app = app    def bind(self, port):        address = ("", port)        self.listen_sock.bind(address)        self.listen_sock.listen(128)    def start(self):        while True:            client_sock, client_addr = self.listen_sock.accept()            print("客户端%s已连接" % (client_addr,))            p = Process(target=self.handle_client, args=(client_sock, client_addr))            p.start()            # 释放client_sock            client_sock.close()    def start_response(self, status_code, response_headers):        resp_start_line = "HTTP/1.0 " + status_code + "\r\n"  # 起始行        # 遍历处理response_headers,形成响应头        resp_headers = ""        for header_name, header_value in response_headers:            resp_headers += (header_name + ": " + header_value + "\r\n")        # 将拼接好的响应报文前半部分保存        self.resp_start_line_headers = resp_start_line + resp_headers    def handle_client(self, c_sock, c_addr):        """        子进程处理客户端        :param c_sock:  socket类型对象  处理客户端通信用到的socket对象        :param c_addr:  元组 (ip, port)  客户端的地址信息        :return: None        """        # 接收客户端发送过来的请求数据, 即http请求报文数据        http_req_data = c_sock.recv(1024)        # 解析客户端的请求报文        http_req_data_str = http_req_data.decode()        # 对http_req_data_str按照"\r\n"分隔符进行拆分        req_start_line = http_req_data_str.split("\r\n")[0]  # 请求的起始行        # 使用正则表达是从起始行中提出请求的文件名        # GET /index.html HTTP/1.1        match_result = re.match(r"(\w+) +(/\S*) +", req_start_line)        req_method = match_result.group(1)        file_path = match_result.group(2)        print("file_path:", file_path)        # 构造一个字典,用来保存解析的数据        environ = {            "PATH_INFO": file_path,            "REQUEST_METHOD": req_method        }        # 如果用户的请求的是/主路径,返回主页信息        response_body = self.app(environ, self.start_response)        resp_data = self.resp_start_line_headers + "\r\n"        c_sock.send(resp_data.encode() + response_body)        # 关闭socket        c_sock.close()def main():    http_server = HttpServer(MyFramework.app)    http_server.bind(PORT)    http_server.start()if __name__ == '__main__':    main()

MyFramework.py

import timePORT = 8080# 用户能够获取的网页数据存放目录HTML_ROOT_DIR = "./html"class Application(object):    def __init__(self, urls):        self.urls = urls    def __call__(self, environ, start_response):        file_path = environ["PATH_INFO"]        if file_path.startswith("/static"):            # 表示用户请求的是静态文件            # path == "/static/index.html"            file_path = file_path[7:]  # 切取文件路径            if file_path == "/":                file_path = "/index.html"            try:                file = open(HTML_ROOT_DIR + file_path, "rb")            except IOError:                # 表示用户请求的文件不存在,要返回404响应报文                status_code = "404 Not Found"  # 响应状态码                response_headers = [("Server", "MyServer"), ("Content-Type", "text")]  # 响应头                start_response(status_code, response_headers)                return b"file not exist"            else:                file_data = file.read()                file.close()                status_code = "200 OK"  # 响应状态码                response_headers = [("Server", "MyServer"), ("Content-Type", "text/html")]  # 响应头                start_response(status_code, response_headers)                return file_data        else:            # 表示用户请求的是动态程序            for view_path, view_fun in self.urls:                if view_path == file_path:                    response_body = view_fun(environ, start_response)                    return response_body.encode()            # 循环执行后,程序仍然没有返回,表示用户请求的路径没有找到,所以需要返回404错误            status_code = "404 Not Found"  # 响应状态码            response_headers = [("Server", "MyServer"), ("Content-Type", "text")]  # 响应头            start_response(status_code, response_headers)            return b"program not exist"def say_hello(environ, start_response):    status_code = "200 OK"    response_headers = ([("Server", "MyServer"), ("Content-Type", "text/html")])    start_response(status_code, response_headers)    return time.ctime()urls = [("/hello", say_hello)]  # 路由列表app = Application(urls)

html文件下下index.html文件

            

你好陌生人

我在学习python

 

转载地址:http://klrum.baihongyu.com/

你可能感兴趣的文章
关于优酷视频代码播放的若干事情……
查看>>
异步与并行~List<T>是线程安全的吗?
查看>>
CentOS7安装mysql提示“No package mysql-server available.”
查看>>
linux下截取给定路径中的目录部分
查看>>
MVC学习随笔----如何在页面中添加JS和CSS文件
查看>>
gulp同步执行任务
查看>>
各种变换滤波和噪声的类型和用途总结
查看>>
rocketmq生产者部署的机器注意事项
查看>>
exp函数
查看>>
MySql的一些用法
查看>>
DAMICON'S LIST OF OPEN SOFTWARE
查看>>
js-用于检测类数组对象的函数
查看>>
php 获取客户端的浏览器信息
查看>>
JavaScript------获取表单信息
查看>>
R语言︱文本挖掘——词云wordcloud2包
查看>>
Chapter 3 Phenomenon——18
查看>>
hibernate+spring整合增删改事务错误
查看>>
怎样理解阻塞与非阻塞、同步与异步的区别?
查看>>
C语言不定参数
查看>>
Python第十五天 datetime模块 time模块 thread模块 threading模块 Queue队列模块 multiprocessing模块 paramiko模块 fab...
查看>>