什么是web服务器的原理是什么

Web框架本质

众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。

  1. #!/usr/bin/env python
  2. #coding:utf-8
  3.  
  4. import socket
  5.  
  6. def handle_request(client):
  7. buf = client.recv(1024)
  8. client.send("HTTP/1.1 200 OK\r\n\r\n")
  9. client.send("Hello, Seven")
  10.  
  11. def main():
  12. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  13. sock.bind(('localhost',8000))
  14. sock.listen(5)
  15.  
  16. while True:
  17. connection, address = sock.accept()
  18. handle_request(connection)
  19. connection.close()
  20.  
  21. if __name__ == '__main__':
  22. main()

上述通过socket来实现了其本质,而对于真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。

WSGI(Web Server Gateway Interface)是一种规范,它定义了使用python编写的web app与web server之间接口格式,实现web app与web server间的解耦。

python标准库提供的独立WSGI服务器称为wsgiref。

  1. from wsgiref.simple_server import make_server
  2.  
  3. def RunServer(environ, start_response):
  4. start_response('200 OK', [('Content-Type', 'text/html')])
  5. return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]
  6.  
  7. if __name__ == '__main__':
  8. httpd = make_server('', 8000, RunServer)
  9. print("Serving HTTP on port 8000...")
  10. httpd.serve_forever()

自定义Web框架

一、框架

通过python标准库提供的wsgiref模块开发一个自己的Web框架

  1. #!/usr/bin/env python
  2. #coding:utf-8
  3. from wsgiref.simple_server import make_server
  4.  
  5. def index():
  6. return 'index'
  7.  
  8. def login():
  9. return 'login'
  10.  
  11. def routers():
  12.  
  13. urlpatterns = (
  14. ('/index/',index),
  15. ('/login/',login),
  16. )
  17.  
  18. return urlpatterns
  19.  
  20. def RunServer(environ, start_response):
  21. start_response('200 OK', [('Content-Type', 'text/html')])
  22. url = environ['PATH_INFO']
  23. urlpatterns = routers()
  24. func = None
  25. for item in urlpatterns:
  26. if item[0] == url:
  27. func = item[1]
  28. break
  29. if func:
  30. return func()
  31. else:
  32. return '404 not found'
  33.  
  34. if __name__ == '__main__':
  35. httpd = make_server('', 8000, RunServer)
  36. print "Serving HTTP on port 8000..."
  37. httpd.serve_forever()

2、模板引擎

在上一步骤中,对于所有的login、index均返回给用户浏览器一个简单的字符串,在现实的Web请求中一般会返回一个复杂的符合HTML规则的字符串,所以我们一般将要返回给用户的HTML写在指定文件中,然后再返回。如:

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. </head>
  7. <body>
  8. <h1>Index</h1>
  9.  
  10. </body>
  11. </html>
  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3.  
  4. from wsgiref.simple_server import make_server
  5.  
  6. def index():
  7. # return 'index'
  8. f = open('index.html')
  9. data = f.read()
  10. return data
  11.  
  12. def login():
  13. # return 'login'
  14. f = open('login.html')
  15. data = f.read()
  16. return data
  17.  
  18. def routers():
  19.  
  20. urlpatterns = (
  21. ('/index/', index),
  22. ('/login/', login),
  23. )
  24.  
  25. return urlpatterns
  26.  
  27. def run_server(environ, start_response):
  28. start_response('200 OK', [('Content-Type', 'text/html')])
  29. url = environ['PATH_INFO']
  30. urlpatterns = routers()
  31. func = None
  32. for item in urlpatterns:
  33. if item[0] == url:
  34. func = item[1]
  35. break
  36. if func:
  37. return func()
  38. else:
  39. return '404 not found'
  40.  
  41. if __name__ == '__main__':
  42. httpd = make_server('', 8000, run_server)
  43. print "Serving HTTP on port 8000..."
  44. httpd.serve_forever()

对于上述代码,虽然可以返回给用户HTML的内容以现实复杂的页面,但是还是存在问题:如何给用户返回动态内容?

  • 自定义一套特殊的语法,进行替换
  • 使用开源工具jinja2,遵循其指定语法

 

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. </head>
  7. <body>
  8. <h1>{{name}}</h1>
  9.  
  10. <ul>
  11. {% for item in user_list %}
  12. <li>{{item}}</li>
  13. {% endfor %}
  14. </ul>
  15.  
  16. </body>
  17. </html>

index.html

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3.  
  4. from wsgiref.simple_server import make_server
  5. from jinja2 import Template
  6.  
  7. def index():
  8. # return 'index'
  9.  
  10. # template = Template('Hello {{ name }}!')
  11. # result = template.render(name='John Doe')
  12.  
  13. f = open('index.html')
  14. result = f.read()
  15. template = Template(result)
  16. data = template.render(name='John Doe', user_list=['alex', 'eric'])
  17. return data.encode('utf-8')
  18.  
  19. def login():
  20. # return 'login'
  21. f = open('login.html')
  22. data = f.read()
  23. return data
  24.  
  25. def routers():
  26.  
  27. urlpatterns = (
  28. ('/index/', index),
  29. ('/login/', login),
  30. )
  31.  
  32. return urlpatterns
  33.  
  34. def run_server(environ, start_response):
  35. start_response('200 OK', [('Content-Type', 'text/html')])
  36. url = environ['PATH_INFO']
  37. urlpatterns = routers()
  38. func = None
  39. for item in urlpatterns:
  40. if item[0] == url:
  41. func = item[1]
  42. break
  43. if func:
  44. return func()
  45. else:
  46. return '404 not found'
  47.  
  48. if __name__ == '__main__':
  49. httpd = make_server('', 8000, run_server)
  50. print "Serving HTTP on port 8000..."
  51. httpd.serve_forever()

动态内容

遵循jinja2的语法规则,其内部会对指定的语法进行相应的替换,从而达到动态的返回内容,对于模板引擎的本质那又是什么?

** 下回分解

Python 第五阶段 学习记录之--- Web框架的更多相关文章

  1. Python 第五阶段 学习记录之---Django 基础

    Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. ...

  2. Python 第五阶段 学习记录之---Django 进阶

    Model 一.创建表 1.基本结构 字段 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bi ...

  3. Python 第五阶段 学习记录之----ORM

    ORM: orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的,为了 ...

  4. Python 第五阶段 学习记录之----rabbmit

    消息服务器rabbmit RabbitMQ 消息队列 python里有两个Q, threading queue.不同线程间数据交互 进程Queue: 不同进程间交互这个说法是错误的. 这个是用于父进程 ...

  5. Python 第八阶段 学习记录之---算法

    算法(Algorithm): 一个计算过程, 解决问题的方法 1.递归的两个特点 - 调用自身 - 结束条件 时间复杂度 - 时间复杂度是用来估计算法运行时间的一个式子(单位) - 一般来说,时间复杂 ...

  6. python 第四阶段 学习记录之----异步

    异步: 知识情况: 1.多线程, 多线程使用场景 1.IO操作不占CPU,读写数据(网络中.系统中) 2.计算占CPU, 3.上下文切换不占CPU.它消耗资源 python多线程 不适合CPU密集型的 ...

  7. Python 第四阶段 学习记录之----多线程

    多线程 多线程例子, 注释部份即为多线程的使用 #-*- coding: utf-8 -*- # Wind clear raise # 2017/3/5 下午2:34 import socket im ...

  8. go语言,golang学习笔记2 web框架选择

    go语言,golang学习笔记2 web框架选择 用什么go web框架比较好呢?能不能推荐个中文资料多的web框架呢? beego框架用的人最多,中文资料最多 首页 - beego: 简约 & ...

  9. [Python之路] 使用装饰器给Web框架添加路由功能(静态、动态、伪静态URL)

    一.观察以下代码 以下来自 Python实现简易HTTP服务器与MINI WEB框架(利用WSGI实现服务器与框架解耦) 中的mini_frame最后版本的代码: import time def in ...

随机推荐

  1. 框架源码系列七:Spring源码学习之BeanDefinition源码学习(BeanDefinition、Annotation 方式配置的BeanDefinition的解析)

    一.BeanDefinition 1. bean定义都定义了什么? 2.BeanDefinition的继承体系  父类: AttributeAccessor: 可以在xml的bean定义里面加上DTD ...

  2. YARN 启动后失败退出——没有请求资源——Invalid resource request, no resources request

    在ambari-server中修改了yarn的配置,重新启动服务,结果RM启动失败,错误也很奇怪,“不合理的资源请求,没有请求任何资源”!详细如下: -- ::, FATAL resourcemana ...

  3. ABBYY PDF Transformer+支持的格式

    ABBYY PDF Transformer+是一个新的,全面的巧妙解决PDF文档的工具,它将泰比的光学字符识别(OCR)技术和Adobe®PDF技术完美结合,以确保实现便捷地处理任何类型的PDF文件, ...

  4. 最强Android书 架构大剖析 作者网站

    http://newandroidbook.com/    jonathan levin   (最强Android书 架构大剖析) http://newandroidbook.com/AIvI-M-R ...

  5. 【CF666E】Forensic Examination 广义后缀自动机+倍增+线段树合并

    [CF666E]Forensic Examination 题意:给你一个字符串s和一个字符串集合$\{t_i\}$.有q个询问,每次给出$l,r,p_l,p_r$,问$s[p_l,p_r]$在$t_l ...

  6. 最新版本sublime text3注册码

    TwitterInc 200 User License EA7E-890007 1D77F72E 390CDD93 4DCBA022 FAF60790 61AA12C0 A37081C5 D03164 ...

  7. E - Stones 优先队列

    来源1896 Because of the wrong status of the bicycle, Sempr begin to walk east to west every morning an ...

  8. Dijkstra模板

    Dijkstra struct node { long long x,d; node(); node(long long xx,long long dd){ x = xx; d = dd; } }; ...

  9. [ERROR] - Error reading string. Unexpected token: StartObject. Path 'formData', line 1, position 13.

    公司流程框架: businessData 为 string 所有要使用JSON.stringify();

  10. php const常量 不能使用字符串连接符.链接

    class jdpay extends pay { const BASE_URL = "https://mapi.jdpay.com/npp10/"; private $agree ...