• (转)Python的web服务器


    1.浏览器请求动态页面过程

    Python的web服务器0

    2.WSGI

    Python Web Server Gateway Interface (或简称 WSGI,读作“wizgy”)。

    WSGI允许开发者将选择web框架和web服务器分开。可以混合匹配web服务器和web框架,选择一个适合的配对。比如,可以在Gunicorn 或者 Nginx/uWSGI 或者 Waitress上运行 Django, Flask, 或 Pyramid。真正的混合匹配,得益于WSGI同时支持服务器和架构.

    web服务器必须具备WSGI接口,所有的现代Python Web框架都已具备WSGI接口,它让你不对代码作修改就能使服务器和特点的web框架协同工作。

    WSGI由web服务器支持,而web框架允许你选择适合自己的配对,但它同样对于服务器和框架开发者提供便利使他们可以专注于自己偏爱的领域和专长而不至于相互牵制。其他语言也有类似接口:java有Servlet API,Ruby 有 Rack。

    3.定义WSGI接口

    WSGI接口定义非常简单,它只要求Web开发者实现一个函数,就可以响应HTTP请求。我们来看一个最简单的Web版本的“Hello World!”:

    def application(environ, start_response):
     start_response('200 OK', [('Content-Type', 'text/html')])
     return 'Hello World!'

    上面的 application( ) 函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:

    • environ:一个包含所有HTTP请求信息的dict对象;
    • start_response:一个发送HTTP响应的函数。

    整个application( )函数本身没有涉及到任何解析HTTP的部分,也就是说,把底层web服务器解析部分和应用程序逻辑部分进行了分离,这样开发者就可以专心做一个领域了.

    application( )函数必须由WSGI服务器来调用。有很多符合WSGI规范的服务器。而我们此时的web服务器项目的目的就是做一个极可能解析静态网页还可以解析动态网页的服务器

    实现代码:

    import time,multiprocessing,socket,os,re
    
    class MyHttpServer(object):
    
     def __init__(self):
     serveSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     self.serveSocket = serveSocket
     self.HTMLPATH = './html'
    
     def bind(self,port=8000):
     self.serveSocket.bind(('',port))
    
     def start(self):
     self.serveSocket.listen()
     while True:
     clientSocket, clientAddr = self.serveSocket.accept()
     print(clientSocket)
     multiprocessing.Process(target=self.serveHandler, args=(clientSocket, clientAddr)).start()
     clientSocket.close()
    
     def serveHandler(self,clientSocket,clientAddr):
     try:
     recvData = clientSocket.recv(1024).decode('gbk')
     fileName = re.split(r' +', recvData.splitlines()[0])[1]
     filePath = self.HTMLPATH
    
     if fileName.endswith('.py'):
     try:
     pyname=fileName[1:-3]
     # 导入
     pyModule = __import__(pyname)
    
     env={}
     responseBody = pyModule.application(env,self.startResponse)
     responseLine = self.responseLine
     responseHeader = self.responseHeader
     except ImportError:
     responseLine = 'HTTP/1.1 404 NOT FOUND'
     responseHeader = 'Server: ererbai' + os.linesep
     responseHeader += 'Date: %s' % time.ctime()
     responseBody = '<h1>很抱歉,服务器中找不到你想要的内容<h1>'
     else:
     if '/'== fileName:
     filePath += '/index.html'
     else:
     filePath += fileName
    
     try:
     file = None
     file =open(filePath,'r',encoding='gbk')
     responseBody = file.read()
    
     responseLine = 'HTTP/1.1 200 OK'
     responseHeader = 'Server: ererbai' + os.linesep
     responseHeader += 'Date:%s' % time.ctime()
     except FileNotFoundError:
     responseLine = 'HTTP/1.1 404 NOT FOUND'
     responseHeader = 'Server: ererbai' + os.linesep
     responseHeader += 'Date:%s' % time.ctime()
     responseBody = '很抱歉,服务器中找不到你想要的内容'
    
    
     finally:
     if (file!=None) and (not file.closed):
     file.close()
    
     except Exception as ex:
     responseLine = 'HTTP/1.1 500 ERROR'
     responseHeader = 'Server: ererbai' + os.linesep
     responseHeader += 'Date: %s' % time.ctime()
     responseBody = '服务器正在维护中,请稍后再试。%s'%ex
     finally:
     senData = responseLine + os.linesep + responseHeader + os.linesep + os.linesep + responseBody
     print(senData)
     senData = senData.encode('gbk')
     clientSocket.send(senData)
     if (clientSocket!=None) and ( not clientSocket._closed):
     clientSocket.close()
    
     def startResponse(self,status,responseHeaders):
     self.responseLine = status
     self.responseHeader = ''
     for k,v in responseHeaders:
     kv = k + ':' + v + os.linesep
     self.responseHeader += kv
    
    
    
    if __name__ == '__main__':
     server = MyHttpServer()
     server.bind(8000)
     server.start()

    服务器中存在的html的文件:

    • index.html
    <html>
    <head>
     <title>首页-毕业季</title>
     <meta http-equiv=Content-Type content="text/html;charset=gbk">
    
    </head>
    <body>我们仍需共生命的慷慨与繁华相爱,即使岁月以刻薄和荒芜相欺。
    </body>
    </html>
    • biye.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
     <meta charset="gbk">
     <title>毕业季</title>
    </head>
    <body>![](http://localhost:51017/day18/html/biyeji.png)
    <br>当年以为六月不过也很平常
    <br>当自己真正经历了毕业
    <br>才知道偶尔看到六月毕业季等字里所流露的种种想要重温却不敢提及的回忆
    <br>毕业了
    <br>那个夏天,我的毕业季,我的青春年少
    <br>六月
    <br>有人笑着说解脱,有人哭着说不舍
    <br>那年,
    <br>你对我说的你好
    <br>在不知不觉中
    <br>变成了
    <br>再见。
    
    </body>
    </html>
    Python的web服务器1 
    biyeji.png

    mytime.py文件

    import time
    def application(env,startResponse):
     status = 'HTTP/1.1 200 OK'
     responseHeaders = [('Server','bfe/1.0.8.18'),('Date','%s'%time.ctime()),('Content-Type','text/plain')]
     startResponse(status,responseHeaders)
    
     responseBody = str(time.ctime())
     return responseBody

    访问结果:

    Python的web服务器2 
    首页
    Python的web服务器3 
    biye.html
    Python的web服务器4 
    mytime.py
    '''
    自定义的符合wsgi的框架
    '''
    import time
    
    
    class Application(object):
     def __init__(self, urls):
     '''框架初始化的时候需要获取路由列表'''
     self.urls = urls
    
     def __call__(self, env, startResponse):
     '''
     判断是静态资源还是动态资源。
     设置状态码和响应头和响应体
     :param env:
     :param startResponse:
     :return:
     '''
     # 从请求头中获取文件名
     fileName = env.get('PATH_INFO')
    
     # 判断静态还是动态
     if fileName.startwith('/static'):
     fileName = fileName[7:]
     if '/' == fileName:
     filePath += '/index.html'
     else:
     filePath += fileName
     try:
     file = None
     file = open(filePath, 'r', encoding='gbk')
     responseBody = file.read()
     status = 'HTTP/1.1 200 OK'
     responseHeaders = [('Server', 'ererbai')]
    
     except FileNotFoundError:
     status = 'HTTP/1.1 404 Not Found'
     responseHeaders = [('Server', 'ererbai')]
     responseBody = '<h1>找不到<h1>'
     finally:
     startResponse(status, responseHeaders)
     if (file != None) and (not file.closed):
     file.close()
     else:
     isHas = False # 表示请求的名字是否在urls中,True:存在,False:不存在
     for url, func in self.urls:
     if url == fileName:
     responseBody = func(env, startResponse)
     isHas = True
     break
     if isHas == False:
     status = 'HTTP/1.1 404 Not Found'
     responseHeaders = [('Server', 'ererbai')]
     responseBody = '<h1>找不到<h1>'
     startResponse(status, responseHeaders)
     return responseBody
    
    
    def mytime(env, startResponse):
     status = 'HTTP/1.1 200 OK'
     responseHeaders = [('Server', 'time')]
     startResponse(status, responseHeaders)
     responseBody = str(time.ctime())
     return responseBody
    
    
    
    
    def mynews(env, startResponse):
     status = 'HTTP/1.1 200 OK'
     responseHeaders = [('Server', 'news')]
     startResponse(status, responseHeaders)
     responseBody = str('xx新闻')
     return responseBody
    
    
    '''路由列表'''
    urls = [
     ('/mytime', mytime),
     ('/mynews', mynews)
    ]
    
    application = Application(urls)
  • 相关阅读:
    职业倾向测验
    TAU调研咨询
    【转】嵌入式软件工程师经典笔试题
    博客开启啦!
    手淘H5移动端适配方案flexible源码分析
    scrollHeight、clientHeight、offsetHeight、scrollTop等的定义以及图解
    nodejs之路探寻
    学习笔记:Vue+Node+Mongodb 构建简单商城系统(二)
    使用Gulp进行代码压缩的步骤以及配置
    学习笔记:webpack深入与实践(一)
  • 原文地址:https://www.cnblogs.com/liujiacai/p/7418309.html
Copyright © 2020-2023  润新知