已经知道怎么让服务器返回静态的网页了,但是还是不能满足需求,网页数据要是能变化的才好,这样我想要的数据才是最新的。
于是就有了WSGI协议(Web Server Gateway Interface),前面我们的调用的只是静态的文件,要是想让网页数据随时变化,就需要引入可执行的代码,即脚本。WSGI协议就提供了这样一个接口,可以根据客户端的请求,调用py文件。WSGI接口接收两个参数:
env:一个包含所有HTTP请求信息的 。(是一个字典)
start_response:一个发送HTTP响应的函数。 (就是客户端要的信息,动态的)
还是一步一步来实现吧:(与返回静态网页不一样的地方只是如果接受到的请求信息是py文件,就调用函数,返回响应信息,其他都是一样的。)
一,创建套接字。
现在我开始学着用面向对象的编程思想去处理问题了,所以创建套接字,可以直接在类的属性里创建。
class Recvsocket(object):
def __init__(self):
self.server = socket(AF_INET, SOCK_STREAM)
self.server.bind(("", 7788))
self.server.listen(5)第二步,等待接收客户端请求,返回新的套接字。
def recvsocket(self):
while True:
self.client_socket, ip_port = self.server.accept()
print("%s:%s>>>正在连接中。。。" % ip_port)
childthread = Thread(target=self.newsocket, args=(self.client_socket,))
childthread.start()第三步,新的套接字处理客户端请求。(最重要的部分)
def newsocket(self , client_socket):
recvdata = self.client_socket.recv(1024)
print("request data:", recvdata)
recv_lines = recvdata.splitlines()
request_start_line = recv_lines[0]
file_name = re.match(r"\w+ +(/[^ ]*) ", request_start_line.decode("utf-8")).group(1)
if file_name.endswith(".py"):
m = __import__(file_name[1:-3]) #1,这是最重要的一步,检测到py文件,提取出文件名,导入模块
env = {}
response_boby = m.application(env , self.start_response) #,2,这是很重要一步,调用导入模块的函数,并得m_time的结果
response = self.response_header + "\r\n" + response_boby #动态文件的响应报文
else:
if "/" == file_name: #如果不是py结尾的请求,就返回静态文件
file_name = "/index.html"
try:
file = open(HTML_ROOT_DIR + file_name , "rb")
except IOError:
self.response_start_line = "HTTP/1.1 404 Not Foud\r\n"
self.response_headers = "Server: pycharm server\r\n"
self.response_boby = "The file is not fund!"
else:
file_data = file.read()
file.close()
self.response_start_line = "HTTP/1.1 200 OK\r\n"
self.response_headers = "Server: pycharm server\r\n"
self.response_boby = file_data.decode("utf-8")
response = self.response_start_line + self.response_headers + "\r\n" + self.response_boby #静态文件的响应报文
print("response data:", response) #不管是静态页面还是动态的,都要返回,与第一个if条件平行
client_socket.send(response.encode("utf-8"))
client_socket.close()第四步,在上面的函数体中导入了一个模块并引用了该模块的函数,所以我们需要单独创建一个py文件。
#coding = utf-8
import time
def application(env,start_response):
status = "200 OK"
server_headers = [
("server", "pycharm server")
]
start_response(status,server_headers) #这也是很重要的一步,返回服务器函数
return time.ctime()第五步,查漏补缺,缺什么补什么
from socket import *
from threading import Thread
import re
import sys
HTML_ROOT_DIR = "./html" #指定静态文件路径
WSGI_PYTHON_DIR = "./wsgipython" #指定动态文件路径
sys.path.insert(1 , WSGI_PYTHON_DIR) #添加详细路径总结WSGI协议究竟做了什么:
1,拿到客户端的请求信息,先将响应状态码和响应头返回给服务器。
(第四步中通过调用start_response函数,将两个参数传回服务器)
2,然后将响应体返回给服务器。(第四步中执行完start_response函数,然后返回time.ctime()结果给服务器的response_boby)
3.至于完整的响应报文,在服务器中拼接完成,不在导入的木块中定义。
完整的代码:
服务器的代码:
#coding = utf-8
from socket import *
from threading import Thread
import re
import sys
HTML_ROOT_DIR = "./html"
WSGI_PYTHON_DIR = "./wsgipython"
sys.path.insert(1 , WSGI_PYTHON_DIR)
class Recvsocket(object):
def __init__(self):
self.server = socket(AF_INET, SOCK_STREAM)
self.server.bind(("", 7788))
self.server.listen(5)
def recvsocket(self):
while True:
self.client_socket, ip_port = self.server.accept()
print("%s:%s>>>正在连接中。。。" % ip_port)
childthread = Thread(target=self.newsocket, args=(self.client_socket,))
childthread.start()
def start_response(self,status,server_headers):
response_header = "HTTP/1.1 " + status + "\r\n"
for header in server_headers:
response_header += "%s:%s\r\n"%header
self.response_header = response_header
def newsocket(self , client_socket):
recvdata = self.client_socket.recv(1024)
print("request data:", recvdata)
recv_lines = recvdata.splitlines()
request_start_line = recv_lines[0]
file_name = re.match(r"\w+ +(/[^ ]*) ", request_start_line.decode("utf-8")).group(1)
if file_name.endswith(".py"):
m = __import__(file_name[1:-3]) #1,这是最重要的一步,检测到py文件,提取出文件名,导入模块
env = {}
response_boby = m.application(env , self.start_response) #,2,这是很重要一步,调用导入模块的函数,并得m_time的结果
response = self.response_header + "\r\n" + response_boby
else:
if "/" == file_name:
file_name = "/index.html"
try:
file = open(HTML_ROOT_DIR + file_name , "rb")
except IOError:
self.response_start_line = "HTTP/1.1 404 Not Foud\r\n"
self.response_headers = "Server: pycharm server\r\n"
self.response_boby = "The file is not fund!"
else:
file_data = file.read()
file.close()
self.response_start_line = "HTTP/1.1 200 OK\r\n"
self.response_headers = "Server: pycharm server\r\n"
self.response_boby = file_data.decode("utf-8")
response = self.response_start_line + self.response_headers + "\r\n" + self.response_boby
print("response data:", response) #不管是静态页面还是动态的,都要返回,与第一个if条件平行
client_socket.send(response.encode("utf-8"))
client_socket.close()
if __name__ == '__main__':
test = Recvsocket()
test.recvsocket()导入的模块代码:
#coding = utf-8
import time
def application(env,start_response):
status = "200 OK"
server_headers = [
("server", "pycharm server")
]
start_response(status,server_headers) #这也是很重要的一步,返回服务器函数
return time.ctime()本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。