Python web服务器

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


 首页 

 这是
首页 ![](http://localhost:49249/课件/day30/html/girl.png)

客户端浏览器


Python web服务器_第1张图片
Paste_Image.png

服务端


Python web服务器_第2张图片
Paste_Image.png

Web服务器动态资源请求

浏览器请求动态页面过程

Python web服务器_第3张图片
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 = '

找不到

%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 = '

找不到

%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

服务端

Python web服务器_第4张图片
Paste_Image.png

客户端浏览器


Python web服务器_第5张图片
Paste_Image.png

你可能感兴趣的:(Python web服务器)