import socket, os.path, threading,uuid
LEN=1024*64
HOME_PAGE='index.html'
HTML_404='404.html'
# web应用的根路径
WEB_ROOT=r'C:\Users\mym\Desktop\暑期上课'
KEY_SESSIONID='SESSIONID'
# url和自定义函数的映射
url_fun_mapping={}
'''
记录session信息
key: 随机字符串
value: { '自定义key':'自定义value' } 用户名、密码等等(自定义)
'''
sessions={}
def main(port=80):
#默认就是ipv4,tcp
server=socket.socket()
server.bind(('0.0.0.0',port))
# 与操作系统有很大关系,需要操作系统支持,有时设置了,也没用
server.listen(5)
print('启动成功!')
while True:
# client就是socket对象,表示该客户的
client,addr=server.accept()
threading.Thread(target=handle,args=(client,addr)).start()
def handle(client,addr):
# 读取请求头信息
fp=client.makefile('r',encoding='utf-8')
line=fp.readline(LEN)
if line=='':
return
# 读取第一行指令
method,url,version=line.split(' ')
print('method:',method)
print('url:',url)
print('version:',version)
headers=readheaders(fp)
print(headers)
# 从header中解析cookie
cookie=parsecookie(headers)
sessionid,session,existsession=handlesession(cookie)
# 发送数据
if url=='/':
url=HOME_PAGE
# 从url中解析纯url,参数
url2,params=parseUrl(url)
# 根据纯url获取与之对应的自定函数
fun=url_fun_mapping.get(url2)
# 如果存在就调用,不存在就按原来的操作继续往下运行
if fun:
ret=fun(params,session=session)
if isinstance(ret,str):
if existsession:
sendhtml(client,ret,None)
else:
sendhtml(client,ret,sessionid)
else:
print('未实现------------------')
else:
# 读文件并发送,采用二进制发送,读一部分发送一部分
if url[0]=='/':
url=url[1:]
filepath=os.path.join(WEB_ROOT,url)
sendfile(client,filepath)
client.close()
def readheaders(fp):
# 读取并封装后面的头信息
headers={}
while True:
line=fp.readline()
# print(line,end='')
if line=='\n':
break
pos=line.index(':')
headers[line[:pos]]=line[pos+2:-1]
return headers
# 发送文件
def sendfile(client,filepath):
if os.path.exists(filepath):
# 发送响应头 response headers
client.send(b'HTTP/1.1 200 OK\r\n')
else:
# 发送响应头 response headers
client.send(b'HTTP/1.1 404 NOT FOUND\r\n')
filepath=os.path.join(WEB_ROOT,HTML_404)
# 截取访问资源的后缀,并转换小写
suffix=filepath[filepath.rindex('.')+1:].lower()
content_type=get_content_type(suffix)
client.send(content_type)
filesize=os.path.getsize(filepath)
client.send(('Content-Length: %s\r\n'%filesize).encode('utf-8'))
client.send(b'Server: shanghaibaolei\r\n')
client.send(b'\r\n')
with open(filepath,'rb') as f:
data=f.read(LEN)
client.sendall(data)
# client.close()
# 根据访问资源的后缀,获取content-type
def get_content_type(suffix):
ret=None
if suffix=='html':
ret=b'Content-Type: text/html;charset=UTF-8\r\n'
elif suffix=='png':
ret=b'Content-Type: image/png\r\n'
elif suffix=='gif':
ret=b'Content-Type: image/gif\r\n'
elif suffix in ['jpg','jpeg']:
ret=b'Content-Type: image/jpeg\r\n'
elif suffix =='css':
ret=b'Content-Type: text/css\r\n'
elif suffix =='js':
ret=b'Content-Type: application/x-javascript\r\n'
return ret
def parseUrl(url):
'''
解析url
/login?username=mayumin&password=123456
截取出url,并将url后的参数封装成dict类型
并返回 url(纯url),dict
'''
params={}
url2=None
pos=url.find('?')
if pos==-1:
return url,params
else:
url2=url[:pos]
params_str=url[pos+1:]
array=params_str.split('&')
for item in array:
name,value=item.split('=')
params[name]=value
return url2,params
def sendhtml(client,html,sessionid):
'''
向浏览器发送html字符串
'''
ret_bytes=html.encode('utf-8')
client.send(b'HTTP/1.1 200 OK\r\n')
client.send(b'Content-Type: text/html;charset=UTF-8\r\n')
client.send(('Content-Length: %s\r\n'%len(ret_bytes)).encode('utf-8'))
client.send(b'Server: shanghaibaolei\r\n')
if sessionid:
cookie='Set-Cookie: %s=%s\n'%(KEY_SESSIONID,sessionid)
client.send(cookie.encode('utf-8'))
client.send(b'\r\n')
client.sendall(ret_bytes)
def parsecookie(headers):
'''
从headers中,取出cookie,并封装成dict对象
'''
retcookie={}
cookiestr=headers.get('Cookie')
if cookiestr:
cookiearray=cookiestr.split(';')
for item in cookiearray:
key,value=item.split('=')
retcookie[key.strip()]=value.strip()
return retcookie
def handlesession(cookie):
'''
1. 从响应头中找到cookie
2. 从cookie中找到 sessionid
3. 如果有sessionid,就不做操作,如果没有,就生成随机字符串,作为key,放入全局变量sessions,value是空的dict
4. 如果没有sessionid,还要通知响应头,发送Set-Cookie: sessionid=123456
'''
global sessions
sessionid=cookie.get(KEY_SESSIONID)
exist=False
session=None
if sessionid==None:# 浏览器发来的cookie中没有sessionid
exist=False
sessionid=str(uuid.uuid1()).replace('-','')
sessions[sessionid]={}
session=sessions[sessionid]
else: # 浏览器发来的cookie中有sessionid
exist=True
session=sessions.get(sessionid)
if session==None: # sessions没有sessionid。场景:服务器重启
sessions[sessionid]={}
session=sessions[sessionid]
return sessionid,session,exist
# 自定义函数
def login(params,session):
print('执行login()---',params)
'''
1. 连接数据库
2. select * from user where username=:1 and password=:2
3. 判断用户是否登录成功
'''
username=params.get('username')
print('username=',username)
password=params.get('password')
print('password=',password)
# 登录成功后,一定要向session放些数据(唯一,可以识别用户,一般情况下:DB中user表的主键,还可以放登录名、性别、一句话介绍。。。。。)
session['userid']='123456789'
return '登录成功!'
def order(params,session):
'''
下订单
'''
# 从业务上:是否登录
# session['userid']
ret=''
userid=session.get('userid')
if userid==None:
ret='未登录!'
else:
ret='已登录,userid=%s'%userid
return ret
def reg(params):
print('执行reg()---',params)
if __name__ == "__main__":
# key:url,value:函数对象
url_fun_mapping['/login']=login
url_fun_mapping['/dologin']=login
url_fun_mapping['/reg']=reg
url_fun_mapping['/order']=order
main()
原文出处:/show_1EF3w3m7LEYs.html