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

<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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354

推荐阅读更多精彩内容

  • 在Web应用中,服务器把网页传给浏览器,实际上就是把网页的HTML代码发送给浏览器,让浏览器显示出来。而浏览器和服...
    壁花烧年阅读 617评论 0 0
  • 一、Web开发 Browser/Server模式目前最流行,简称BS架构。在BS架构下,客户端只需要浏览器,应用程...
    时间之友阅读 854评论 0 0
  • HTTP协议介绍: HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写 H...
    界面大叔阅读 203评论 0 0
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,654评论 18 139
  • 汕头趁早读书会是在2015年1月2日成立的。起初只是我一个人的想法,然后建群建微博,在母星公众号下占有一席之位,之...
    萤喵阅读 389评论 0 1