专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

57挑战之53,python实现客户端+服务端

ins518 2024-11-23 16:45:11 技术文章 12 ℃ 0 评论

希望这是最后一次写53题了。昨天下午花了2小时,完全重新盘了一遍。

不过写出来后,感觉稍微加深了一些对python处理http 的理解,也算没白弄。

介绍题目下:


红框里要求写一个安卓或者ios的app,直接连接到后端服务器,(自己写代码),实现创建API 来获取列表及存储文件。

不废话,实现架构如下图:


  • 之前客户端已经做好了,参考文章:

https://www.toutiao.com/article/7087364110660223522/

  • 服务端也已经做好,参考文章:

https://www.toutiao.com/article/7091078001969922568/

  • redis 操作,参考文章

https://www.toutiao.com/article/7089633631219663392/

上代码:

客户端代码:clientside.py

from flask import Flask,render_template,request,url_for,redirect
from datetime import date
import requests
import json
import time

def getdate():
    return date.today()

def post(url,note):
    timestring = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    post_data = json.dumps({timestring:note})
    req = requests.post(url,json=post_data)
    print(req.text)

app = Flask(__name__)
@app.route('/',methods=['GET','POST'])
@app.route('/index')
@app.route('/home')
def index():
    if request.method == 'POST':
       notes = request.form['notes']
       url = 'http://127.0.0.1:8008'
       post(url,notes)
       return render_template('display.html',info=notes)

    if request.method == 'GET':
       return render_template('index.html')

@app.route('/list',methods=['GET'])
def list():
    r = requests.get("http://127.0.0.1:8008/list")
    info2 = json.loads(r.text)
    return render_template('showall.html',info2=info2)

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=80,debug = True)

服务端代码:webapi.py

from http.server import BaseHTTPRequestHandler, HTTPServer
import json
import cgi
import serverside
from serverside import get_input,judge_input,insert_into_redis,drop_redis,display_redis



class Server(BaseHTTPRequestHandler):
    def _set_headers(self):
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()

    def do_HEAD(self):
        self._set_headers()

    # GET sends back a Hello world message
    def do_GET(self):
        self._set_headers()
        message1 = json.dumps({'hello': 'world', 'received': 'ok'})
        response1 = bytes(json.dumps(message1), 'utf-8')
        self.wfile.write(response1)
        d1=display_redis()
        message2 = json.dumps(d1)
        response2 = bytes(json.dumps(message2),'utf-8')
        self.wfile.write(response2)
    # POST echoes the message adding a JSON field
    def do_POST(self):
        ctype, pdict = cgi.parse_header(self.headers.get('content-type'))
        # refuse to receive non-json content
        if ctype != 'application/json':
            self.send_response(400)
            self.end_headers()
            return

        # read the message and convert it into a python dictionary
        length = int(self.headers.get('content-length'))
        message = json.loads(self.rfile.read(length))
        print(message)
        print(type(message))
        dic=json.loads(message)
        #print(message.values())
        #print(list(message.values())[0])
        values=list(dic.values())[0]
        print(values)
        print(type(values))
        insert_into_redis(values)

        #print(type(message.values()))
        #print(message.keys())
        #print(type(message.keys()))

        # add a property to the object, just to mess with data
        #message['received'] = 'ok'
        # send the message back
        self._set_headers()
        response = bytes(json.dumps(message),'utf-8')
        self.wfile.write(response)

def run(server_class=HTTPServer, handler_class=Server, port=8008):
    server_address = ('', port)
    httpd = server_class(server_address, handler_class)
    print('Starting httpd on port {0}...'.format(port))
    httpd.serve_forever()


if __name__ == "__main__":
    from sys import argv

    if len(argv) == 2:
        run(port=int(argv[1]))
    else:
        run()


服务端代码2:

"""
replace 方法支持替代一次,用下面的方案
replace() 方法
比如,输入的字符串为’one two one two one’,第一个参数为替换前的参数,第二个为替换后的参数。默认会替换字符串中的所有符合条件的字符串。

s = 'one two one two one'

print(s.replace(' ', '-'))
# one-two-one-two-one
1
2
3
4
也可以指定一个最大替换次数值,一旦指定,只会替换前面匹配的n个字符串。

print(s.replace('one', 'XXX'))
# XXX two XXX two XXX

print(s.replace('one', 'XXX', 2))
# XXX two XXX two one
————————————————
版权声明:本文为CSDN博主「独家雨天」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013019701/article/details/104056898


"""

import redis
from redis import StrictRedis, ConnectionPool
import re
import json
import time


def get_input():
    # 输入键盘数据,返回键盘的输入数据
    instructions = """  
    Please provide a task which you want input,
    if you wanna write a task,with the format like this:
    new notes go to school today
    if you wanna list the task, with the format like this:
    list notes
    if you wanna delete some note, you can use list task to check the notes id ,
    then use this command to delete the note
    delete note id 1
    if you wanna stop writing
    just enter a blank ,then the loop will not continue
    """
    print(instructions)
    values = input("Please provide the information")
    return values


def judge_input(values):
    # 判断获取到的字符串的含义,如果是插入则插入,如果是删除则删除,如果是显示,则显示,如果是空白则退出循环
    if re.match("new notes", values) != None:
        hanyi = 0
        value = values.replace("new notes ", '', 1)
    if re.match("list notes", values) != None:
        hanyi = 2
        value = values.replace("list notes ", '', 1)
    if re.match("delete note id", values) != None:
        hanyi = 1
        value = values.replace("delete note id ", '', 1)
    if re.match(" ", values) != None:
        hanyi = 3
        value = " "
    return hanyi, value


def insert_into_redis(value):
    # 如果含义为插入,则做插入操作
    pool = ConnectionPool(host='localhost', port=6379, db=0, decode_responses=True)
    # redis 取出的结果默认是字节,我们可以设定 decode_responses=True 改成字符串。
    r = StrictRedis(connection_pool=pool)
    if r.hkeys('note') == []:
        id = 1
    else:
        id = int(max(r.hkeys('note'))) + 1
    string = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    r.hset("note", id, json.dumps({"date": string, "content": value}))
    print("The value {0} is inserted".format(value))


def drop_redis(value):
    # 如果含义是删除,则做删除操作
    pool = ConnectionPool(host='localhost', port=6379, db=0, decode_responses=True)
    r = StrictRedis(connection_pool=pool)
    r.hdel('note', value)
    print("the date {} has been removed".format(value))


def display_redis():
    # 如果含义是展示,则做展示
    print("** displayed")
    pool = ConnectionPool(host='localhost', port=6379, db=0, decode_responses=True)
    r = StrictRedis(connection_pool=pool)
    d1 = {}
    for k in r.hkeys('note'):
        print("id is {0}: ".format(k), end="")
        d = r.hget('note', k)  #d是一个字符串
        d1.update({k:d}) #制作一个字典,key 是id, value 是字符串
        #print(type(json.loads(d))) #debug 用,这里可以看到返回的类型是字典
        #print(type(d)) #debug 用,这里可以看到返回的类型是字符串
        print(json.loads(d))
    for values in d1.values(): #debug 用
        print(values) #debug 用,展示所有value 的信息
    print(d1) #debug 用,展示所有字典的信息
    return d1

if __name__ == "__main__":
    while 1:
        values = get_input()
        hanyi, notes = judge_input(values)
        if hanyi == 0:
            # 如果是插入,则做插入操作
            insert_into_redis(notes)
        if hanyi == 1:
            # 如果是删除,则做删除操作
            drop_redis(notes)
        if hanyi == 2:
            # 如果是展示,则做展示操作
            display_redis()
        if hanyi == 3:
            # 如果含义是退出,则跳出循环
            break

客户端的几个HTML ,很简单

index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>57-53</title>
</head>
<body>
<form method = "post">
<label for="name">please provide the note which you wanna input</label>
<input type="text" name="notes" required><br>
<input type="submit" name="submit" value="记录">
</form>
</body>
</html>

showall.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>57-53</title>
</head>
<body>
{{info2}}
</body>
</html>

display.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>57-53</title>
</head>
<body>
{{info}}
</body>
</html>

效果图:

登录html 后插入:前端截图



后端的截图:


从数据库里面可以查到这条信息


直接list 8008服务端是能看到所有数据了。


明天把list 问题解决后补在本文档。

留一个作业 list的时候报错了。




--added next day

在昨天的基础上做一下debug,从下文可以查到,response 相关信息的内容:

参考https://blog.csdn.net/qq_39208536/article/details/107881396


可以看到,返回是一个response 格式,utf-8 编码,

可以用命令r.content.decode('utf-8') 对它解码。

可以用命令r.json() 对内容做反序列化,昨天反序列化失败的原因是,在服务端代码里面一次返回了两个消息,因此处理失败。我把服务端确认的那端代码直接干掉,问题解决。


客户端(80) list 的效果截图


客户端python 进程返回结果(蓝框)

服务端返回值:


Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表