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.pngWSGI
了解了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.py
py模块
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
网友评论