zoukankan      html  css  js  c++  java
  • Python基础Web服务器案例

    一、WSGI

    1、PythonWeb服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI) 是Python应用程序或框架和Web服务器之间的一种接口,已经被广泛接受, 它已基本达成它的可移植性方面的目标。

    2、WSGI 没有官方的实现, 因为WSGI更像一个协议。 只要遵照这些协议, WSGI应用(Application)都可以在任何服务器(Server)上运行, 反之亦然。

    3、WSGI允许开发者将选择web框架和web服务器分开,web服务器必须具备WSGI接口。

    4、示例:浏览器请求动态页面过程

    二、Web动态服务器代码示例

    1、目录结构 

    2、服务器 MyWebServer.py  

      1 # coding:utf-8
      2 
      3 import socket
      4 import re
      5 import sys
      6 
      7 from multiprocessing import Process
      8 
      9 # 设置框架文件根目录
     10 FRAMEWORK_DIR = "./Frameworks"
     11 
     12 
     13 class HTTPServer(object):
     14     """web服务器"""
     15     def __init__(self, application):
     16         """构造函数, application指的是框架的app"""
     17         self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     18         # 服务端close时释放端口
     19         self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
     20         # web框架
     21         self.app = application
     22         # 响应头
     23         self.response_headers = ""
     24 
     25     def start(self):
     26         """服务器启动"""
     27         self.server_socket.listen(128)
     28         while True:
     29             client_socket, client_address = self.server_socket.accept()
     30             # print("[%s : %s]用户连接上了" % (client_address[0],client_address[1]))
     31             print("[%s, %s]用户连接上了
    " % client_address)
     32             # 开启多进程,处理客户端请求
     33             handle_client_process = Process(target=self.handle_client, args=(client_socket,))
     34             handle_client_process.start()
     35             client_socket.close()
     36 
     37     def start_response(self, status, headers):
     38         """传递给web框架的方法(回调),用来获得框架返回的状态、headers"""
     39         response_headers = "HTTP/1.1 " + status + "
    "
     40         for header in headers:
     41             response_headers += "%s: %s
    " % header
     42         # 在服务器中记录框架返回的响应头
     43         self.response_headers = response_headers
     44 
     45     def handle_client(self, client_socket):
     46         """处理客户端请求"""
     47 
     48         # 获取客户端请求数据
     49         request_data = client_socket.recv(1024)
     50         print("客户端的请求数据:
    ", request_data.decode("utf-8"))
     51         request_lines = request_data.splitlines()
     52         print("将请求数据按照每一行切片:
    ")
     53         for index in range(len(request_lines)-1):
     54             print("第%d行: %s"%(index+1,request_lines[index].decode("utf-8")))
     55 
     56         # 解析请求报文:提取用户请求的文件名、方法名
     57         request_start_line = request_lines[0]
     58         print(request_start_line.decode("utf-8"))
     59         file_name = re.match(r"w+ +(/[^ ]*) ", request_start_line.decode("utf-8")).group(1)
     60         method = re.match(r"(w+) +/[^ ]* ", request_start_line.decode("utf-8")).group(1)
     61         env = {
     62             "PATH_INFO": file_name,
     63             "METHOD": method
     64         }
     65 
     66         # 传入请求参数和响应回调方法,获得响应体内容:此处把对象当做函数直接来用,会掉对象的__call__方法
     67         response_body = self.app(env, self.start_response)
     68 
     69         # 拼接出完整的回复内容:响应头 + 响应体
     70         response = self.response_headers + "
    " + response_body
     71 
     72         # 向客户端返回响应数据:python3中必须是 bytes()返回的bytes对象
     73         client_socket.send(bytes(response, "utf-8"))
     74 
     75         # 关闭客户端连接
     76         client_socket.close()
     77 
     78     def bind(self, port):
     79         self.server_socket.bind(("", port))
     80 
     81 
     82 def main():
     83 
     84     # 增加检索包的路径
     85     sys.path.insert(1, FRAMEWORK_DIR)
     86 
     87     # 获取程序启动参数
     88     if len(sys.argv) < 2:
     89         sys.exit("ERROR, you should input :python3 MyWebServer.py [Module]:app")
     90     module_name, app = sys.argv[1].split(":")
     91 
     92     # 动态载入模块
     93     m = __import__(module_name)
     94 
     95     # 获取模块中的属性:此处是web框架的实例对象
     96     app = getattr(m, app)
     97 
     98     # 创建并开启服务器
     99     http_server = HTTPServer(app)
    100     http_server.bind(8888)
    101     http_server.start()
    102 
    103 
    104 if __name__ == "__main__":
    105     main()

    3、web框架 MyWebFramework.py

      1 # coding:utf-8
      2 
      3 import time
      4 
      5 # from MyWebServer import HTTPServer
      6 
      7 # 设置静态文件根目录
      8 HTML_ROOT_DIR = "./html"
      9 
     10 
     11 class Application(object):
     12     """框架的核心部分,也就是框架的主题程序,框架是通用的"""
     13     def __init__(self, urls):
     14         # 设置路由信息
     15         self.urls = urls
     16 
     17     def __call__(self, env, start_response):
     18         """将类名当做函数来直接调用,重写此方法。此处方法的作用是返回给服务器响应体"""
     19 
     20         # 获取文件名(路径),默认为"/"
     21         path = env.get("PATH_INFO", "/")
     22 
     23         # 判断是静态还是动态文件
     24         if path.startswith("/static"):
     25             # 要访问静态文件: /static/index.html
     26             file_name = path[7:]
     27             # 打开文件,读取内容
     28             try:
     29                 file = open(HTML_ROOT_DIR + file_name, "rb")
     30             except IOError:
     31                 # 代表未找到路由信息,404错误
     32                 status = "404 Not Found"
     33                 headers = []
     34                 # 调用传入的回调方法,将状态和头部信息返回
     35                 start_response(status, headers)
     36                 # 直接返回响应体
     37                 return "Page not found"
     38             else:
     39                 # 读取文件内容
     40                 file_data = file.read()
     41                 file.close()
     42 
     43                 # 设置响应内容
     44                 status = "200 OK"
     45                 headers = []
     46                 start_response(status, headers)
     47                 return file_data.decode("utf-8")
     48         else:
     49             # 访问动态文件,查询路由表中是否包含要执行的文件(是否有路由信息)
     50             for url, handler in self.urls:
     51                 if path == url:
     52                     # handler 即为路由表中映射的方法(非字符串)
     53                     return handler(env, start_response)
     54 
     55             # 代表未找到路由信息,404错误
     56             status = "404 Not Found"
     57             headers = []
     58             start_response(status, headers)
     59             return "Program not found"
     60 
     61 
     62 def show_time(env, start_response):
     63     status = "200 OK"
     64     headers = [
     65         ("Content-Type", "text/plain")
     66     ]
     67     # 调用传入的回调方法,将状态和头部信息返回
     68     start_response(status, headers)
     69     return time.ctime()
     70 
     71 
     72 def print_hello(env, start_response):
     73     status = "200 OK"
     74     headers = [
     75         ("Content-Type", "text/plain")
     76     ]
     77     start_response(status, headers)
     78     return "hello everyone"
     79 
     80 
     81 def print_json(env, start_response):
     82     status = "200 OK"
     83     headers = [
     84         ("Content-Type", "text/plain")
     85     ]
     86     start_response(status, headers)
     87     jsonStr = "{"code":200,"data": {"list":[{"firstName":"Qi","lastName":"Zhang"}]},"msg":"OK"}"
     88     return jsonStr
     89 
     90 
     91 def show_default(env, start_response):
     92     try:
     93         file = open(HTML_ROOT_DIR + "/index.html", "rb")
     94     except IOError:
     95         status = "404 Not Found"
     96         headers = []
     97         start_response(status, headers)
     98         return "DefaultPage not found"
     99     else:
    100         file_data = file.read()
    101         file.close()
    102         status = "200 OK"
    103         headers = []
    104         start_response(status, headers)
    105         return file_data.decode("utf-8")
    106 
    107 
    108 # 路由信息,根据映射表,动态调用web框架中的方法
    109 urls = [("/", show_default),
    110         ("/time", show_time),
    111         ("/hello", print_hello),
    112         ("/json", print_json)]
    113 
    114 # 通过路由表实例化对象(当前模块载入时就会创建),直接提供给服务器
    115 app = Application(urls)

    4、执行

    (1)从业务和使用逻辑上,应该是“启动”服务器,所以运行服务器程序

    (2)配置程序参数

     

      

     (3)浏览器验证: 127.0.0.1:8888 、 json 127.0.0.1:8888/json  、127.0.0.1:8888/static/index.html

  • 相关阅读:
    JMF:Screen Grabber [DataSource]
    ImageUtilities.loadImage第二个参数的说明
    PipeStateListener和PipeEventListener
    as3 htmlText常用标签
    jsfl批量导出swf
    java socket安全策略文件
    模拟EventCenter,flash自带的事件机制的一个解耦框架,callback回调方式用于模块之间的通信
    flashDevelop快捷键和几个实用的插架
    as3 用StyleSheet css 设置文本样式
    as3 位图九宫格
  • 原文地址:https://www.cnblogs.com/cleven/p/10735243.html
Copyright © 2011-2022 走看看