美文网首页程序员
Python web服务器

Python web服务器

作者: PythonMaO | 来源:发表于2017-06-20 21:42 被阅读242次

    Web静态服务器

    显示静态的页面

    import socket
    import multiprocessing
    import os,re
    import time
    
    G_PATH = './html'
    def client(clientSocket,recvAddr):
        recvDate=clientSocket.recv(1024).decode('gbk')
        print(recvDate)
        a=recvDate.splitlines()[0]
        fileName=re.split(' +',a)[1]
        filePath = G_PATH
        if '/' == fileName:
            filePath += '/首页.html'      #默认首页
        else:
            filePath += fileName
        try:
            file = None
            file = open(filePath, 'r',encoding='gbk')
            responseBody = file.read()
    
            print(responseBody)
            responseLine = 'HTTP/1.1 200 OK'+os.linesep
            responseHeader = 'Server: laowang'+os.linesep+'Date: %s'%time.ctime() + os.linesep
        except FileNotFoundError:
            responseLine = 'HTTP/1.1 404 OK' + os.linesep
            responseHeader = 'Server: laowang' + os.linesep + 'Date: %s' % time.ctime() + os.linesep
            responseBody = '找不到'
        except Exception as ex:
            responseLine = 'HTTP/1.1 500 OK' + os.linesep
            responseHeader = 'Server: laowang' + os.linesep + 'Date: %s' % time.ctime() + os.linesep
            responseBody = '服务器正在升级中,请稍后再试。。。。。。%s'%ex
        finally:
            if (file != None) and (not file.closed):
                file.close()
    
        sendDate=(responseLine+responseHeader+os.linesep+responseBody).encode('gbk')
        clientSocket.send(sendDate)
        clientSocket.close()
    
    
    def main():
        serveSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        serveSocket.bind(('',10086))
        serveSocket.listen()
        while True:
            clientSocket,clientAddr = serveSocket.accept()
            multiprocessing.Process(target=client,args=(clientSocket,clientAddr)).start()
            clientSocket.close()
    
    
    if __name__ == '__main__':
        main()
    

    首页.html

    <html>
    <title> 首页 </title>
    <meta charset="utf-8">
    <body> 这是<br>首页</body>
    ![](http://localhost:49249/课件/day30/html/girl.png)
    
    </html>
    

    客户端浏览器


    Paste_Image.png

    服务端


    Paste_Image.png

    Web服务器动态资源请求

    浏览器请求动态页面过程

    Paste_Image.png

    WSGI

    了解了HTTP协议和HTML文档,我们其实就明白了一个Web应用的本质就是:

    浏览器发送一个HTTP请求;

    服务器收到请求,生成一个HTML文档;

    服务器把HTML文档作为HTTP响应的Body发送给浏览器;

    浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示。

    所以,最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。Apache、Nginx、Lighttpd等这些常见的静态服务器就是干这件事情的。

    如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。

    正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。

    这个接口就是WSGI:Web Server Gateway Interface。

    定义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()函数中,调用:

    start_response('200 OK', [('Content-Type', 'text/html')])
    

    整个application()函数本身没有涉及到任何解析HTTP的部分,也就是说,底层代码不需要我们自己编写,我们只负责在更高层次上考虑如何响应请求就可以了。

    动态资源请求服务端代码

    import socket, multiprocessing, re, time, os
    
    
    class myServerModule:
        def __init__(self):
            serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.serverSocket = serverSocket
            self.HTMLPATH = './html'
    
        def bind(self, port=10086):
            self.serverSocket.bind(('', port))
    
        def start(self):
            self.serverSocket.listen()
            while True:
                clientSocket, clientAddr = self.serverSocket.accept()
                multiprocessing.Process(target=self.clientHandler, args=(clientSocket, clientAddr)).start()
                clientSocket.close()
    
        def clientHandler(self, clientSocket, clientAddr):
            try:
                recvData = clientSocket.recv(1024).decode('gbk')
                print(recvData)
                fileName = re.split(r' +', recvData.splitlines()[0])[1]
                filePath = self.HTMLPATH
                if fileName.endswith('.py'):
                    try:
                        pyName = fileName[1:-3]
                        print(pyName)
                        pyModule = __import__(pyName)
                        env = {}
                        responseBody = pyModule.application(env, self.startResponse)
                        responseLine = self.responseLine
                        responseHeader = self.responseHeader
                    except ImportError as ex:
                        responseLine = 'HTTP/1.1 404 NOT FOUND' + os.linesep
                        responseHeader = 'Server: laowang' + os.linesep
                        responseHeader += 'Date: %s' % time.ctime() + os.linesep
                        responseBody = '<h1>找不到<h1>%s' % ex
                else:
                    if '/' == fileName:
                        filePath += '/首页.html'
                    else:
                        filePath += fileName
    
                    try:
                        file = None
                        file = open(filePath, 'r', encoding='gbk')
                        responseBody = file.read() + filePath
    
                        responseLine = 'HTTP/1.1 200 OK' + os.linesep
                        responseHeader = 'Server: laowang' + os.linesep
                        responseHeader += 'Date: %s' % time.ctime() + os.linesep
                    except FileNotFoundError as ex:
                        responseLine = 'HTTP/1.1 404 NOT FOUND' + os.linesep
                        responseHeader = 'Server: laowang' + os.linesep
                        responseHeader += 'Date: %s' % time.ctime() + os.linesep
                        responseBody = '<h1>找不到<h1>%s' % ex
                    finally:
                        if (file != None) and (not file.closed):
                            file.close()
            except Exception:
                responseLine = 'HTTP/1.1 500 ERROR' + os.linesep
                responseHeader = 'Server: laowang' + os.linesep
                responseHeader += 'Date: %s' % time.ctime() + os.linesep
                responseBody = '服务器正在升级中,请稍后再试。。。。。。'
            finally:
                sendData = (responseLine + responseHeader + os.linesep + responseBody).encode('gbk')
                clientSocket.send(sendData)
                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 = myServerModule()
        server.bind(10086)
        server.start()
    
    

    还有一个mytime.pypy模块

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

    服务端

    Paste_Image.png

    客户端浏览器


    Paste_Image.png

    相关文章

      网友评论

        本文标题:Python web服务器

        本文链接:https://www.haomeiwen.com/subject/etvaqxtx.html