httpserver代码如下
import socket
import pymysql
import re
from uuid import uuid4
from datetime import datetime, timedelta
# 1. 识别不同的网址 --> 返回不同的页面
# 2. 能够加载外部的html文件进来
# 3. 服务器去链接数据库
# 4. 注册功能 --> 插入一条数据到mysql中
# 5. 登陆功能 --> 在数据库中查询 在注册的时候插入的账户密码是否匹配
# 6. 保持登陆 --> cookie 或者 session
HOME_DIR = '.\html'
class HttpServer():
def __init__(self):
self.ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 重启不改端口号
self.ss.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.ss.bind(('127.0.0.1', 8080))
self.ss.listen(10)
self.session_id = None # session默默认为None
print('HTTP服务器已启动...')
def start(self):
while True:
conn, addr = self.ss.accept()
try:
msg = conn.recv(1024)
url = self.get_url_argument(msg) # url是个列表,里面存了url、用户参数和cookie
func, res, info = self.url_header_list(url) #参数url数据直接返回到info中
# 得到session_id,加入到响应报文
cookie = self.set_cookie(self.session_id)
# 响应报文
response_header = 'HTTP/1.1 OK\r\nContent-Type:text/html\r\n' \
'Connection:Close\r\n'
response_body = func(res, info)
conn.send((response_header + cookie + response_body).encode())
conn.close()
except Exception as e:
conn.close()
print(e)
# 把的url和对应的逻辑函数、资源路径和请求参数返回一个tuple
def url_header_list(self, url):
if url[0] == '/':
res = HOME_DIR + '\\index.html'
return (self.index, res, url)
if url[0] == '/index.html':
res = HOME_DIR + '\\index.html'
return (self.index, res, url)
elif url[0] == '/login.html':
print(url)
res = HOME_DIR + '\\login.html'
return (self.login, res, url)
elif url[0] == '/register.html':
res = HOME_DIR + '\\register.html'
return (self.register, res, url)
elif url[0] == '/exit':
res = HOME_DIR + '\\index.html'
return (self.main_exit, res, url)
else:
res = HOME_DIR + '\\error.html'
return (self.error, res, url[1])
# 请求报文切割url和请求argument
def get_url_argument(self, msg):
msg = msg.decode()
msg_list = msg.split('\r\n\r\n')
info_dict = {} # 参数信息,放入字典
request_info = [] # 打包所有信息的列表
request_msg = msg_list[0].split() # 切割请求报文,找到url
request_info.append(request_msg[1]) # 把url放入列表
cookie = self.get_cookie(msg) # 获取cookie信息
if msg_list[1] != '': # 从请求报文里切割传递的参数,并放入字典
info_list = msg_list[1].split('&')
info1 = info_list[0].split('=')
info2 = info_list[1].split('=')
info_dict[info1[0]] = info1[1]
info_dict[info2[0]] = info2[1]
request_info.append(info_dict) # 把信息字典放入列表
request_info.append(cookie) # 把cookie放入列表
return request_info
else:
request_info.append(info_dict)
request_info.append(cookie) # 把cookie放入列表
return request_info
# 连接mysql数据库
def mysql_conn(self):
conn = pymysql.connect(
host='127.0.0.1',
user='root', password='root',
database='httpweb',
charset='utf8')
return conn
# 进入首页,判断session是否过期,未过期直接登录。
def index(self, res, info):
html = res
count, username = self.get_session(info[2])
if info is not None:
# count, username = self.get_session(info[2])
if count > 0:
html = HOME_DIR + '\\main.html'
with open(html, encoding='utf-8') as f:
response_body = f.read()
try:
response_body = self.render(response_body, username)
except Exception:
print("报错")
print(response_body)
return response_body
def main_exit(self, res, info):
delete = self.del_session(info[2])
print(delete)
with open(res, encoding='utf-8') as f:
response_body = f.read()
return response_body
# 进入错误页面
def error(self, res, info):
with open(res, encoding='utf-8') as f:
response_body = f.read()
return response_body
# 进入登录界面和登录逻辑
def login(self, res, info):
if not info[1]:
with open(res, encoding='utf-8') as f:
response_body = f.read()
return response_body
else:
count, user_info = self.login_dao(info[1])
if count > 0:
session = self.set_session(user_info[0])
html = '\\main.html'
else:
html = '\\login_fail.html'
with open(HOME_DIR+html, encoding='utf-8') as f:
response_body = f.read()
response_body = self.render(response_body, user_info[1])
return response_body
# 进入注册界面和注册逻辑
def register(self, res, info):
if not info[1]:
with open(res, encoding='utf-8') as f:
response_body = f.read()
return response_body
else:
html = ''
is_exist = self.user_exists(info[1])
if is_exist > 0:
html = '\\register_fail.html'
else:
count = self.register_dao(info[1])
if count > 0:
html = '\\login.html'
else:
html = '\\register_error.html'
with open(HOME_DIR+html, encoding='utf-8') as f:
response_body = f.read()
return response_body
# 登录dao函数
def login_dao(self, info):
sql_conn = self.mysql_conn()
username = info['username']
password = info['password']
sql = "select * from users where `name`='{}' and `password`='{}'".format(username, password)
cursor = sql_conn.cursor()
count = cursor.execute(sql)
user_info = cursor.fetchone()
cursor.close()
sql_conn.commit()
sql_conn.close()
return count, user_info
# 注册dao函数
def register_dao(self, info):
sql_conn = self.mysql_conn()
username = info['username']
password = info['password']
sql = "insert into users (`name`,`password`) values ('{}','{}')".format(username, password)
cursor = sql_conn.cursor()
count = cursor.execute(sql)
sql_conn.commit()
sql_conn.close()
return count
# 判断用户是否存在dao函数
def user_exists(self, info):
sql_conn = self.mysql_conn()
username = info['username']
sql = "select * from users where `name`='{}'".format(username)
cursor = sql_conn.cursor()
count = cursor.execute(sql)
cursor.close()
sql_conn.commit()
sql_conn.close()
return count
# 利用正则表达式替换html中的内容,渲染技术
def render(self, data, replace):
pattern = re.compile('{{ }}')
res = re.sub(pattern, replace, data)
return res
# 设置cookie
def set_cookie(self, session_id):
cookie = 'Set-Cookie: session_id={}\r\n\r\n'.format(session_id)
return cookie
# 获取cookie,把session_id从请求报文切割出来
def get_cookie(self, msg):
msg_list = msg.split('\r\n')
for msg in msg_list:
if msg.startswith('Cookie:'):
cookies = msg[len("Cookie:"):]
cookie_list = cookies.split(';')
for cookie in cookie_list:
cookie = cookie.replace(' ', "")
if cookie.startswith('session_id='):
serect_key = cookie.split('=')[-1]
return serect_key
break
return None
# 获取5天后时间
def get_time(self, days=5):
return datetime.now() + timedelta(days=days)
# 设置session,把session放入数据库中
def set_session(self, users_id):
# del_session = self.del_all_session(users_id) # 多浏览器,不使用删除所有session
# print(del_session)
sql_conn = self.mysql_conn()
session_id = self.gen_uuid()
self.session_id = session_id
sql = "insert into `session` (serect_key, validate, users_id) values('{}', '{}', '{}')".format(session_id, self.get_time(), users_id)
cursor = sql_conn.cursor()
count = cursor.execute(sql)
cursor.close()
sql_conn.commit()
sql_conn.close()
return count
# 获取session,从数据库中查找用户是否有未过期的session数据
def get_session(self, info):
session_id = info
sql_conn = self.mysql_conn()
cursor = sql_conn.cursor()
# 根据session有效时间查,暂时没写
sql = "select users.name from `session` join users on `session`.users_id=users.id where `session`.serect_key='{}'".format(session_id)
count = cursor.execute(sql)
res = None
if count > 0:
res = cursor.fetchone()
sql_conn.commit()
cursor.close()
sql_conn.close()
if res is None:
return count, res
else:
return count, res[0]
# 用uuid生成唯一码作为session
def gen_uuid(self):
return uuid4().hex
# 删除用户当前session
def del_session(self, info):
session_id = info
sql_conn = self.mysql_conn()
cursor = sql_conn.cursor()
sql = "delete from `session` where serect_key='{}'".format(session_id)
count = cursor.execute(sql)
sql_conn.commit()
cursor.close()
sql_conn.close()
return count
if __name__ == '__main__':
hp = HttpServer()
hp.start()
目录格式