自定义的web服务器
点击查看代码
import socket
import threading
import sys
import time
import Myframework
class MyHttpWebServer(object):
def __init__(self,port):
# 创建http服务器的套接字
server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 设置端口号复用,程序退出之后不需要等待几分钟,直接释放端口
server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
server_socket.bind(('',port))
server_socket.listen(128)
self.server_socket = server_socket
# 处理浏览器请求的函数
@staticmethod
def handle_browser_request(new_socket):
# 接受客户端发送过来的数据
recv_data = new_socket.recv(4096)
# 如果没有收到数据,那么请求无效,关闭套接字,直接退出
if len(recv_data) == 0:
new_socket.close()
return
# 对接受的字节数据,转换成字符
request_data = recv_data.decode('utf-8')
print('浏览器请求的数据:',request_data)
request_array = request_data.split(' ',maxsplit=2)
# 得到请求的路径
request_path = request_array[1]
print('请求的路径是:',request_path)
if request_path == '/': # 如果请求的路径为根目录,自动设置为/index.html
request_path = '/index.html'
if request_path.endswith('.html'):
'''动态资源的请求'''
# 动态资源的处理交给web框架来处理,需要把请求参数传给web框架,可能会有多个参数,所有采用字典结构
params = {
'request_path':request_path
}
response = Myframework.handle_request(params)
new_socket.send(response)
new_socket.close()
else:
'''静态资源的请求'''
# 其实就是:根据请求路径读取/static目录中静态的文件数据,响应给客户端
response_first = None # 响应头的第一行
response_header = None # 响应头
response_body = None # 响应主体
try:
# 读取static文件中对应的文件数据,rb模式:是一种兼容模式,可以打开图片,也可以打开js
with open('static'+request_path,'rb') as f:
response_body = f.read()
response_first = 'HTTP/1.1 200 OK\r\n'
response_header = 'Server: myserver\r\n'
except Exception as e: # 浏览器想读取的文件可能不存在
with open('static/404.html','rb') as f:
response_body = f.read() # 响应的主体页面内容(字节)
# 响应头
response_first = 'HTTP/1.1 404 Not Found\r\n'
response_header = 'Server: myserver\r\n'
finally: # 不管if和else有没有执行finally最后都会执行
# 组成响应数据,发送给客户端(浏览器)
response_data = (response_first + response_header + '\r\n').encode('utf-8') + response_body
new_socket.send(response_data)
new_socket.close() # 关闭套接字
# 启动服务器,并且接受客户端的请求
def start(self):
# 循环并且多线程来接受客户端请求
while True:
new_socket,ip_port = self.server_socket.accept()
print('客户端的ip和端口',ip_port)
# 一个客户端请求交给一个线程处理
sub_thread = threading.Thread(target=self.handle_browser_request,args=(new_socket,))
sub_thread.setDaemon(True) # 设置当前线程为守护线程
sub_thread.start() # 子线程启动
def main():
web_server = MyHttpWebServer(8080)
web_server.start()
if __name__ == '__main__':
main()
自定义的web框架
点击查看代码
import time
from functools import wraps
import pymysql
route_lst = []
# 定义路由装饰器
def route(request_path): # 参数就是url请求
def add_route(func):
# 添加路由到路由表
route_lst.append((request_path, func))
@wraps(func)
def invoke():
# 调用我们指定的处理函数,并且返回结果
return func()
return invoke
return add_route
# 我们自定义的web框架
def handle_request(params):
request_path = params['request_path'] # 这里的路径是url上面输入的路径名
for path, func in route_lst:
if request_path == path:
return func()
else: # 没有动态资源的数据 返回404
return page_not_found()
# 如果是index页面 就返回index页面的数据
# if request_path == '/index.html':
# return index()
# # 如果是userinfo页面就返回userinfo页面的数据
# elif request_path == '/userinfo.html': # request_path是url上面输入的路径名
# return user_info()
# # 如果请求的动态资源没有,就返回404
# else:
# return page_not_found()
# 动态资源页面
@route('/index.html')
def index():
conn = pymysql.connect(host='localhost', port=3306, user='root', password='root', database='test', charset='utf8')
cursor = conn.cursor()
sql = 'select * from t_movies'
cursor.execute(sql)
result = cursor.fetchall()
datas = ''
for row in result:
datas += '''<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 = '删除'/></td>
</tr>
''' % row
# date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
# response_body = data # 响应的主体内容
with open('template/index.html', 'r', encoding='utf-8') as f:
response_body = f.read()
response_body = response_body.replace('{%dates%}', datas)
# 响应头
response_first = 'HTTP/1.1 200 OK\r\n'
response_header = 'Server: myserver\r\n'
response_data = (response_first + response_header + '\r\n' + response_body).encode('utf-8')
return response_data
# 专门处理user_info.html的动态请求的函数
@route('/userinfo.html')
def user_info():
date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
# response_body = data # 响应的主体内容
with open('template/user_info.html', 'r', encoding='utf-8') as f: # 这里的user_info.html指的是文件名
response_body = f.read()
response_body = response_body.replace('{%dates%}', date)
# 响应头
response_first = 'HTTP/1.1 200 OK\r\n'
response_header = 'Server: myserver\r\n'
response_data = (response_first + response_header + '\r\n' + response_body).encode('utf-8')
return response_data
def page_not_found():
with open('static/404.html', 'rb') as f:
response_body = f.read() # 响应的主体页面内容(字节)
# 响应头
response_first = 'HTTP/1.1 404 Not Found\r\n'
response_header = 'Server: myserver\r\n'
response_data = (response_first + response_header + '\r\n').encode('utf-8') + response_body
return response_data