※TIPS:python文件直接命令行执行方式参考:怎么用cmd命令行窗口运行python文件_tyq_666的博客-优快云博客_cmd运行python文件
命令行执行语句:
打开命cmd命令提示行窗口,输入 cd + 存放.py文件夹路径,按下回车键(Enter键)
输入 py HTTP_Server.py,按下回车键(Enter键),即可成功运行服务器
※TIPS:postman调试工具官网:Postman API Platform
目前使用一个全局字典存放所有的task任务,服务器掉电后重新初始化;
※postman测试,直接用JSON格式收包,可以接收中文字符
任务存放格式如下:
字段: | ||
key | 键值:由服务器自动分配 | self.keyvalue = keyvalue |
title | 任务名称 | self.taskname = taskname |
address | 任务执行的地点 | self.address = address |
S-time | 任务开始时间 | self.begintime = begintime |
E-time | 任务结束时间 | self.endtime = endtime |
contents | 任务具体内容 | self.contents = contents |
step | 阶段 | self.step = step |
importance | 重要性 | self.importance = importance |
status | 状态 | self.status = status |
目前实现的功能(所有数据传输通过json字符串传输)注意:IP地址为主机地址,用ipconfig指令查看:
1、客户端通过get服务,获取所有任务信息,目前通过get服务直接返回在网页body体中;
实现效果:
①通过浏览器直接访问对应的IP服务,获取全部任务:http://192.168.28.16:8080/alltask
※192.168.28.16是对应的本地服务器IP地址,/alltask是目前允许访问的url
②通过postman调试工具get服务,获取全部任务信息:
postman获取的结果:
<html>
<head>
<title>TO-DO_Screen</title>
</head>
<body>
<p>Welcome to TO-DO_Screen!</p>
<p>ALL_TASK_begin</p>
<p>{"keyvalue": 1, "taskname": "Learn how to use TO-DO_Screen", "address": "kitchen", "begintime": "19:00",
"endtime": "21:00", "contents": "default_contents", "step": "default_step", "importance": "default_importance",
"status": "default_status"}</p>
<p>{"keyvalue": 2, "taskname": "Learn how to add task", "address": "office", "begintime": "8:00", "endtime": "9:00",
"contents": "default_contents", "step": "default_step", "importance": "default_importance", "status":
"default_status"}</p>
<p>{"keyvalue": 3, "taskname": "Learn how to del task by keyvalue", "address": "bedroom", "begintime": "22:00",
"endtime": "23:00", "contents": "default_contents", "step": "default_step", "importance": "default_importance",
"status": "default_status"}</p>
<p>ALL_TASK_end</p>
<p>You accessed path: /alltask</p>
</body>
</html>
GET request for /alltask
2、客户端通过post服务,追加指定任务,keyvalue由服务器自动分配,并且返回给客户端:
例:追加任务:sleeping
除keyvalue字段之外,其余字段均需要存在
post语句:
{"TASK_ID": "ADD", "keyvalue": 0, "taskname": "sleeping", "address": "bedroom", "begintime": "24:00", "endtime": "8:00", "contents": "default_contents", "step": "default_step", "importance": "default_importance", "status": "default_status"}
TASK_ID_ADD-keyvalue:4;ADD_SUCCESS:可以看到服务器自动分配的keyvalue是4,并且追加成功;
再次get获取全部任务查看:
3、客户端通过post服务,删除指定任务,keyvalue为唯一匹配点,并且返回给客户端:
如果不存在对应的任务返回信息,提示删除失败,如果有提示删除结果;
例:删除任务3:
除keyvalue字段之外,其余字段均发送空白即可
post语句:{"TASK_ID": "DEL", "keyvalue": 3, "taskname": "", "address": "", "begintime": "", "endtime": "", "contents": "", "step": "", "importance": "", "status": ""}
TASK_ID_DEL-keyvalue:3;DEL_SUCCESS:可以看到提示删除任务3成功;
再次get获取全部任务查看:
再次尝试删除任务3,因为任务3不存在,所以无法删除:
TASK_ID_DEL-keyvalue:3;DEL_Failed-no_keyvalue:提示没有对应的keyvalue,删除失败;
4、客户端通过post服务,修改指定任务,keyvalue为唯一匹配点,需要修改的字段设置内容,不需要修改的字段默认为空即可,并且返回给客户端:
如果不存在对应的任务返回信息,提示修改失败,如果有提示修改结果;
例:修改任务2的开始时间和结束时间:
除keyvalue字段之外,其余需要修改的字段有内容即可,无需修改的字段发送空白即可
post语句:{"TASK_ID": "CHANGE", "keyvalue": 2, "taskname": "", "address": "", "begintime": "6:00", "endtime": "8:00", "contents": "", "step": "", "importance": "", "status": ""}
TTASK_ID_CHANGE-keyvalue:2;CHANGE_SUCCESS:可以看到提示修改任务3成功;
再次get获取全部任务查看,任务2的指定字段已被修改:
再次尝试修改不存在的任务3,因为任务3不存在,所以无法修改:
TASK_ID_CHANGE-keyvalue:3;CHANGE_Failed-no_keyvalue:提示没有对应的keyvalue,修改失败;
※postman测试,直接用JSON格式收包,可以接收中文字符
服务器端完成源码:
from http.server import BaseHTTPRequestHandler, HTTPServer
import logging
import json
import copy
from collections import OrderedDict
# python 使用类创建结构体
class Taskclass(object):
class Struct(object):
def __init__(self, keyvalue, taskname, address, begintime, endtime, contents, step, importance, status):
self.keyvalue = keyvalue
self.taskname = taskname
self.address = address
self.begintime = begintime
self.endtime = endtime
self.contents = contents
self.step = step
self.importance = importance
self.status = status
def make_struct(self, keyvalue, taskname, address, begintime, endtime, contents, step, importance, status):
return self.Struct(keyvalue, taskname, address, begintime, endtime, contents, step, importance, status)
#服务器结构体
class S(BaseHTTPRequestHandler):
def do_HEAD(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
#get服务获取当前所有的任务
def do_GET(self):
paths = {
'/alltask': {'status': 200}, #success
'/fob': {'status': 404}, #cant find
'/err': {'status': 500} #failed
}
print(self.path)
if self.path in paths:
self.respond(paths[self.path])
else:
self.respond({'status': 500})
logging.info("GET request,\nPath: %s\nHeaders:\n%s\n", str(self.path), str(self.headers))
self.wfile.write("GET request for {}".format(self.path).encode('utf-8'))
#追加或者削除任务
def do_POST(self):
content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
post_data = self.rfile.read(content_length) # <--- Gets the data itself
logging.info("POST request,\nPath: %s\nHeaders:\n%s\n\nBody:\n%s\n",
str(self.path), str(self.headers), post_data.decode('utf-8'))
res = "Your TASK_STR: " + post_data.decode('utf-8')
TASK_STR_json = ""
TASK_DICT = {}
TASK_STR_json = post_data.decode('utf-8')
print(TASK_STR_json)
print(type(TASK_STR_json))
TASK_DICT = json.loads(TASK_STR_json)
print(TASK_DICT)
print(type(TASK_DICT))
TASK_ID = ""
TASK_ID = TASK_DICT["TASK_ID"]
print(TASK_ID)
if TASK_ID == "ADD" or TASK_ID == "DEL" or TASK_ID == "CHANGE":
if TASK_ID == "ADD":
keyvalue = Task_ADD(
TASK_DICT["taskname"],
TASK_DICT["address"],
TASK_DICT["begintime"],
TASK_DICT["endtime"],
TASK_DICT["contents"],
TASK_DICT["step"],
TASK_DICT["importance"],
TASK_DICT["status"]
)
res = res + "-TASK_ID_ADD-" + "keyvalue:" + str(keyvalue) + ";ADD_SUCCESS"
if TASK_ID == "DEL":
keyvalue = TASK_DICT["keyvalue"]
Del_RES = Task_DEL(keyvalue)
if Del_RES == 1:
res = res + "-TASK_ID_DEL-" + "keyvalue:" + str(keyvalue) + ";DEL_Failed-no_keyvalue"
else:
res = res + "-TASK_ID_DEL-" + "keyvalue:" + str(keyvalue) + ";DEL_SUCCESS"
if TASK_ID == "CHANGE":
keyvalue = TASK_DICT["keyvalue"]
CHANGE_RES = Task_CHANGE(keyvalue, TASK_DICT)
if CHANGE_RES == 1:
res = res + "-TASK_ID_CHANGE-" + "keyvalue:" + str(keyvalue) + ";CHANGE_Failed-no_keyvalue"
#未对应
elif CHANGE_RES == 2:
res = res + "-TASK_ID_CHANGE-" + "keyvalue:" + str(keyvalue) + ";CHANGE_Failed-Dict_ERR"
else:
res = res + "-TASK_ID_CHANGE-" + "keyvalue:" + str(keyvalue) + ";CHANGE_SUCCESS"
else:
res = res + "-TASK_ID_ERR"
self.do_HEAD()
# self.wfile.write("POST request for {}".format(self.path).encode('utf-8'))
self.wfile.write("{}".format(res).encode('utf-8'))
# self.wfile.write("POST request for {ASS}".format(data).encode('utf-8'))
def respond(self, opts):
response = self.handle_http(opts['status'], self.path)
self.wfile.write(response)
def handle_http(self, status_code, path):
self.send_response(status_code)
content = ""
if status_code == 200:
self.send_header('Content-type', 'text/html')
self.end_headers()
task_str = ""
task_str = print_Dict_Task(Dict_Task)
content = '''
<html><head><title>TO-DO_Screen</title></head>
<body>
<p>Welcome to TO-DO_Screen!</p>
<p>ALL_TASK_begin</p>
{}
<p>ALL_TASK_end</p>
<p>You accessed path: {}</p>
</body></html>
'''.format(task_str, path)
return bytes(content, 'UTF-8')
global Dict_Task #暂时用来全局存储任务队列的字典
global Task_KEY
#打印数据结构用的print函数
def print_Taskclass(testclass):
str_out = ""
str_out = "keyvalue:" + str(testclass.keyvalue) \
+ ";taskname:" + str(testclass.taskname)\
+ ";address:" + str(testclass.address)\
+ ";begintime:" + str(testclass.begintime)\
+ ";endtime:" + str(testclass.endtime) \
+ "contents:" + str(testclass.contents) \
+ ";step:" + str(testclass.step) \
+ ";importance:" + str(testclass.importance) \
+ ";status:" + str(testclass.status)
print(str_out)
# print(testclass.keyvalue)
# print(testclass.taskname)
# print(testclass.address)
# print(testclass.begintime)
# print(testclass.endtime)
#打印字典用的print函数
def print_Dict_Task(testdict):
print(len(testdict))
task_str_re = ""
str_h = "<p>"
str_t = "</p>"
#直接print
# for key in testdict:
# print_Taskclass(testdict[key])
#单条数据转json类型
for key in testdict:
Dict_testSingle = {}
Dict_testSingle = Dict_testSingle.clear()
Dict_testSingle = OrderedDict()
Dict_testSingle["keyvalue"] = testdict[key].keyvalue
Dict_testSingle["taskname"] = testdict[key].taskname
Dict_testSingle["address"] = testdict[key].address
Dict_testSingle["begintime"] = testdict[key].begintime
Dict_testSingle["endtime"] = testdict[key].endtime
Dict_testSingle["contents"] = testdict[key].contents
Dict_testSingle["step"] = testdict[key].step
Dict_testSingle["importance"] = testdict[key].importance
Dict_testSingle["status"] = testdict[key].status
Task_json = json.dumps(Dict_testSingle)
print(Task_json)
print(type(Task_json))
#服务器打包
task_str_re = task_str_re + str_h + Task_json + str_t
# students = json.loads(Task_json)
# print(students)
# print(type(students))
return task_str_re
#Dict_Task追加任务
def Task_ADD(taskname, address, begintime, endtime, contents, step, importance, status):
global Dict_Task
global Task_KEY
Task_KEY = Task_KEY + 1 #服务器自动分配KEY
#新建task结构体
myclass = Taskclass()
t_taskclass = myclass.make_struct(Task_KEY, taskname, address, begintime, endtime, contents, step, importance, status)
# print_Taskclass(t_taskclass)
Dict_Task[Task_KEY] = copy.deepcopy(t_taskclass)
print("Task:" + str(Task_KEY) + "-ADD_OK")
return Task_KEY
#Dict_Task删除任务
def Task_DEL(keyvalue):
global Dict_Task
res = 0
if keyvalue in Dict_Task:
del(Dict_Task[keyvalue])
print("Task:" + str(keyvalue) + "-DEL_OK")
else:
print("Task:" + str(keyvalue) + "-DEL_NG")
res = 1
return res
#Dict_Task修改任务
def Task_CHANGE(keyvalue, TASK_DICT):
global Dict_Task
res = 0
if keyvalue in Dict_Task:
if TASK_DICT["taskname"] != "":
Dict_Task[keyvalue].taskname = TASK_DICT["taskname"]
if TASK_DICT["address"] != "":
Dict_Task[keyvalue].address = TASK_DICT["address"]
if TASK_DICT["begintime"] != "":
Dict_Task[keyvalue].begintime = TASK_DICT["begintime"]
if TASK_DICT["endtime"] != "":
Dict_Task[keyvalue].endtime = TASK_DICT["endtime"]
if TASK_DICT["contents"] != "":
Dict_Task[keyvalue].contents = TASK_DICT["contents"]
if TASK_DICT["step"] != "":
Dict_Task[keyvalue].step = TASK_DICT["step"]
if TASK_DICT["importance"] != "":
Dict_Task[keyvalue].importance = TASK_DICT["importance"]
if TASK_DICT["status"] != "":
Dict_Task[keyvalue].status = TASK_DICT["status"]
print("Task:" + str(keyvalue) + "-CHANGE_OK")
else:
print("Task:" + str(keyvalue) + "-CHANGE_NG")
res = 1
return res
def run(server_class=HTTPServer, handler_class=S, port=8080):
print("run()")
logging.basicConfig(level=logging.INFO)
server_address = ('', port)
httpd = server_class(server_address, handler_class)
logging.info('Starting httpd...\n')
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
print("httpd.server_close()")
logging.info('Stopping httpd...\n')
if __name__ == '__main__':
from sys import argv
Dict_Task = {}
Dict_Task = Dict_Task.clear()
print(Dict_Task)
Dict_Task = OrderedDict()
Task_KEY = 0
key = Task_ADD('Learn how to use TO-DO_Screen', 'kitchen', '19:00', "21:00", "default_contents", "default_step", "default_importance", "default_status")
key = Task_ADD('Learn how to add task', 'office', '8:00', "9:00", "default_contents", "default_step", "default_importance", "default_status")
key = Task_ADD('Learn how to del task by keyvalue', 'bedroom', '22:00', "23:00", "default_contents", "default_step", "default_importance", "default_status")
# res = Task_DEL(1)
#服务器打包
ss = print_Dict_Task(Dict_Task)
print(ss)
if len(argv) == 2:
run(port=int(argv[1]))
else:
run()