一、WebServer.py文件
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
#author:tangyl
import socket
import threading
import Framwork
class HttpWebServer(object):
def __init__(self):
# 创建tcp服务器套接字
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
# 绑定端口号
tcp_server_socket.bind(("",8000))
# 这只监听
tcp_server_socket.listen(128)
self.tcp_server_socket = tcp_server_socket
@staticmethod # 声明以下为静态方法
def headle_client_request(new_socket):
# 接受客户端请求信息
recv_data = new_socket.recv(4096)
if len(recv_data) == 0:
new_socket.close()
return
# 对二进制进行解码
recv_content = recv_data.decode("utf-8")
# 对空格进行分割
request_list = recv_content.split(" ",maxsplit=2)
# 获取请求的资源路径
request_path = request_list[1]
# 判断请求是否是根目录,如果是根目录设置返回的信息
if request_path == "/":
request_path = "/index.html"
# 判断是否是动态资源请求,以后把后缀是.html请求的任务是动态资源请求
if request_path.endswith(".html"):
'''请求动态资源'''
# 请求参数给web框架进行处理
# 准备给web框架的参数信息,以后给web服务器的参数信息都要放到字典里里面
# web服务器负责吧框架反悔的数据封装成报文后发送给浏览器
env = {
"request_path":request_path
}
# 请求动态web框架
status, headers, response_body = Framwork.handle_request(env)
# print(status,headers,response_body)
# 响应行
response_line = "HTTP/1.1 %s\r\n" % status
# 响应头
response_header = ""
for header in headers:
response_header += "%s: %s\r\n" % header
# 响应报文
response_data = (response_line +
response_header +
"\r\n" +
response_body).encode("UTF-8")
# 发送响应报文给浏览器
new_socket.send(response_data)
new_socket.close()
else:
'''请求静态资源'''
# 打开文件读取里面数据,提示这里使用rb兼容图片
try:
with open("static" + request_path,"rb") as file: # 这里的file表示打开文件的对象
file_data = file.read()
except Exception as e:
response_line = "HTTP/1.1 404 Not found\r\n"
# 响应头
response_header = "Server:PWS/1.0\r\n"
with open("static/error.html","rb") as file:
file_data = file.read()
response_pody = file_data
# 把数据封装成http,响应报文格式的数据
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_pody
new_socket.send(response)
else:
response_line = "HTTP/1.1 200 OK\r\n"
# 响应头
response_header = "Server:PWS/1.0\r\n"
# 响应体
response_pody = file_data
# 把数据封装成http,响应报文格式的数据
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_pody
new_socket.send(response)
new_socket.close()
def Start(self):
while True:
new_socket,ip_prot = self.tcp_server_socket.accept()
# 代码执行到此,说明建立成功
sub_thread=threading.Thread(target=self.headle_client_request,args=(new_socket,))
# 设置为守护主进程
sub_thread.setDaemon(True)
sub_thread.start()
# 判断是否主程序代码
def main():
# 等待客户端的连接请求
Webserver = HttpWebServer()
Webserver.Start()
if __name__ == "__main__":
main()
二、Framwork.py文件
'''Web框架职责专门负责处理动态资源请求'''
from datetime import date
from os import curdir
import time,pymysql
import json
route_list = [
# ("/index.html", index),
# ("/center.html", center),
]
def route(path):
# 装饰器
def decorator(func):
# 当装饰器执行时候将路由添加到路由列表里面
route_list.append((path,func))
def inner():
result = func()
return result
return inner
return decorator
@route("/index.html")
def index():
# 状态信息
status = "200 OK"
# 响应头信息
respones_header = [("Server", "PWS/1.1")]
# 1,打开制定模版文件,读取模版文件中的数据
with open("template/index.html","r",encoding='utf8') as file:
data_file = file.read()
conn = pymysql.connect(host="db_url",
user="root",
passwd="password",
database="stock_db",
charset="utf8")
# 获取游标
cursor = conn.cursor()
# 准备sql
sql = "select * from info;"
# 执行sql
cursor.execute(sql)
# 获取查询结果
result = cursor.fetchall()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
# 2,查询数据库,模版里的模版变量({%content})替换成以后从数据库查询后的数据
# 获取当前时间
data = ""
for row in result:
data += """<tr>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td><input type="button" value="添加" id="toAdd" name="toAdd" systemidvaule="000007"></td>
</tr>""" % row
respones_body = data_file.replace("{%content%}", data)
# 这里返回的是元组
return status, respones_header, respones_body
# 获取个人中心数据接口
@route("/center_data.html")
def center_data():
# 从数据库吧数据查询出来,然后再把查询数据转化成为json数据
conn = pymysql.connect(host="db_url",
user="root",
passwd="password",
database="stock_db",
charset="utf8")
cursor = conn.cursor()
sql = '''SELECT i.code, i.short, i.chg, i.turnover, i.price, i.highs, f.note_info
from info i INNER join focus f
on i.id = f.info_id;'''
cursor.execute(sql)
result = cursor.fetchall()
# 把元组转成列表字典
center_data_list = [ { "code":row[0],
"short":row[1],
"chg":row[2],
"turnover":row[3],
"price":str(row[4]),
"highs":str(row[5]),
"note_info":row[6],
}for row in result ]
# 将列表转换成json格式
# ensure_ascii=False表示在控制台显示中文
json_str = json.dumps(center_data_list,ensure_ascii=False)
cursor.close()
conn.close()
status = "200 OK"
# 响应头信息
respones_header = [("Server", "PWS/1.1"),
# 指定编码格式,因为没有模版文件,可以通过响应头编码格式。
("content-type", "text/html; charset=utf-8")
]
return status, respones_header, json_str
@route("/center.html")
def center():
# 状态信息
status = "200 OK"
# 响应头信息
respones_header = [("Server", "PWS/1.1")]
# 1,打开制定模版文件,读取模版文件中的数据
with open("template/center.html","r",encoding='utf8') as file:
data_file = file.read()
# 2,查询数据库,模版里的模版变量({%content})替换成以后从数据库查询后的数据
respones_body = data_file.replace("{%content%}"," ")
# 这里返回的是元组
return status, respones_header, respones_body
def not_found():
# 状态信息
status = "404 Not Found"
# 响应头信息
respones_header = [("Server", "PWS/1.1")]
date = "Not Found"
return status,respones_header,date
# 处理动态资源请求
def handle_request(env):
# 获取动态请求资源
request_path = env["request_path"]
# print("动态资源路径:",request_path)
for path,func in route_list:
if request_path == path:
result = func()
return result
else:
result = not_found()
return result