1、web服务器端
web.py
# 1、导入包
import socket
import threading
import framework
# 2、定义一个HTTPWebServer类
class HTTPWebServer(object):
# 3、定义一个__init__初始化函数
def __init__(self):
# 4、创建套接字对象
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 5、设置端口复用
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 6、绑定端口
tcp_server_socket.bind(('', 8000))
# 7、设置监听
tcp_server_socket.listen(128)
# 8、将套接字赋值给类自己的属性
self.tcp_server_socket = tcp_server_socket
@staticmethod
def handle_client_request(conn_socket):
# 15、接收客户端的HTTP请求数据
client_request_data = conn_socket.recv(1024).decode('utf-8')
# 16、判断接收数据是否为空
if len(client_request_data) > 0:
print(client_request_data)
# 17、获取Ajax发送过来的所有HTTP请求,并按行分割
request_data = client_request_data.split('\r\n')
# print(request_data)
# 18、使用pop方法,弹出request_data中的下标为0的元素,并赋值给请求行
request_line = request_data.pop(0)
# 19、将请求行按空格分割
request_line_data = request_line.split(' ')
# print(request_line_data)
# 20、定义一个空字典,把请求头的信息放入字典中
request_header = {}
# 21、遍历请求头,并将其数据存放字典
for header in request_data:
if header == '':
continue
key = header.split(': ')[0]
value = header.split(': ')[1]
request_header[key] = value
# print(request_header)
# 22、获取请求资源路径
request_path=request_line_data[1]
print(request_path)
# 23、获取用户的请求参数
request_query=request_path.split('?')
# 24、判断请求参数的长度是否大于1,从而判断是否有参数
if len(request_query)>1:
request_path=request_query[0]
query_str=request_query[1]
else:
query_str=None
# 25、将获取的请求路径,请求参数以及请求头组装为字典格式
requests={
'path':request_path,
'query_str':query_str,
'header':request_header
}
# 26、编写符合wsgi协议的数据格式,发送给web应用程序
env={
'request_path':request_path,
'requests':requests
}
# 27、响应数据给浏览器客户端
# 响应行
request_line='HTTP/1.1 200 OK\r\n'
# 响应头
response_header = 'Server:pwb\r\nAccess-Control-Allow-Credentials:true\r\nAccess-Control-Allow-Origin:*\r\nAccess-Control-Allow-Methods:GET, POST, PUT\r\nAccess-Control-Allow-Headers:X-Custom-Header\r\n'
# 响应体
request_body=framework.handle_request(env)
# 拼装响应数据
request_data=(request_line+response_header+'\r\n'+request_body).encode('utf-8')
# 28、返回数据给客户端
conn_socket.send(request_data)
# 29、关闭客户端连接
conn_socket.close()
def start(self):
while True:
# 11、接收客户端发送的HTTP请求连接,并创建新的套接字
conn_socket, ip_port = self.tcp_server_socket.accept()
# 12、创建子线程
sub_thread = threading.Thread(target=self.handle_client_request, args=(conn_socket,))
# 13、设置守护主线程
sub_thread.setDaemon(True)
# 14、开启子线程
sub_thread.start()
if __name__ == '__main__':
# 9、设置入口函数,并对类进行实例化对象
web_server = HTTPWebServer()
# 10、对象调用类的start方法创建线程和新的套接字
web_server.start()
2、web应用程序
framework.py
# 导入pymsql模块
import pymysql
import json
def index(env):
# 返回首页的数据
# 创建连接
conn = pymysql.connect(host='localhost', port=3306, user='root', password='123123', database='book',charset='utf8')
# 获取游标
cursor = conn.cursor()
# 执行sql语句
sql = "select * from bookinfo;"
cursor.execute(sql)
# print(cursor.fetchall())=> ((), (), ()) => [{}, {}, {}] => json.dumps => json_str
stock_data = cursor.fetchall()
center_data_list = []
for data in stock_data:
center_data_list.append({
"id": data[0],
"name": data[1],
"auth": data[2],
"img_url": data[3],
"rank": data[4]
})
# 把以上得到的图书信息转换为JSON格式的字符串
json_str = json.dumps(center_data_list, ensure_ascii=False)
# 关闭游标与连接
cursor.close()
conn.close()
# 返回数据给web.py
return json_str
def detail(env):
# 返回图书的详细数据
# 返回客户端请求的图书id编号(如id=100)
query_str = env['requests']['query_str']
# 创建连接
conn = pymysql.connect(host='localhost', port=3306, user='root', password='123123', database='book', charset='utf8')
# 获取游标
cursor = conn.cursor()
# 执行SQL语句
sql = "select * from bookinfo where %s;" % query_str
cursor.execute(sql)
row = cursor.fetchone()
data_dict = {
"id": row[0],
"name": row[1],
"auth": row[2],
"img_url": row[3],
"read": row[5],
"comment": row[6],
"score": row[8],
"content": row[7],
"synopsis": row[9]
}
# json.dumps只能转换列表和字典
json_str = json.dumps(data_dict, ensure_ascii=False)
# 把图书的阅读量进行+1操作
sql = "update bookinfo set bread=bread+1 where %s;" % query_str
cursor.execute(sql)
conn.commit()
# 关闭游标和连接
cursor.close()
conn.close()
# 返回JSON格式数据给客户端浏览器
return json_str
def handle_request(env):
request_path = env['request_path']
if request_path == '/index':
# 用户想要请求首页数据
return index(env)
elif request_path == '/detail':
# 用户想要请求图书详细页面
return detail(env)
else:
return '404 Not Found...'