在线字典查询项目设计文档

文章目录

  • 在线字典查询项目设计文档
    • 功能要求
      • 基本要求
        • 用户可以登录和注册
        • 可以通过基本的图形界面print以提示客户端输入
      • 界面要求
        • 客户端启动后即进入一级界面,包含如下功能:登录 注册 退出
        • 用户登录后进入二级界面,功能如下:查单词 历史记录 注销
    • 需求分析
      • 多并发方案—多进程
      • 网络传输方法—TCP
      • 技术细节
      • 数据库设计
      • 模块设计
        • 整体概述
        • 客户端模块- client
        • 服务端模块- server
        • 数据库操作模块- db_operate
  • 完整代码
    • 客户端(client.py)
    • 服务器(server.py)
    • 数据库操作(dboperate.py)

功能要求

基本要求
用户可以登录和注册
登录凭借用户名和密码登录
注册要求用户必须填写用户名,密码,其他内容自定
用户名要求不能重复
要求用户信息能够长期保存
可以通过基本的图形界面print以提示客户端输入
程序分为服务端和客户端两部分
客户端通过print打印简单界面输入命令发起请求
服务端主要负责逻辑数据处理
启动服务端后应该能满足多个客户端同时操作
界面要求
客户端启动后即进入一级界面,包含如下功能:登录 注册 退出
退出后即退出该软件
登录成功即进入二级界面,失败回到一级界面
注册成功可以回到一级界面继续登录,也可以直接用注册用户进入二级界面
用户登录后进入二级界面,功能如下:查单词 历史记录 注销
选择注销则回到一级界面
查单词:循环输入单词,得到单词解释,输入特殊符号退出单词查询状态
历史记录:查询当前用户的查词记录,要求记录包含name word time。可以查看所有记录或者前10条均可。

需求分析

多并发方案—多进程

应对多个用户登录情况,可行方案主要有多进程、多线程、多路IO复用,均可选择,本例使用多进程Process实现

方案 实现方法
多进程 os模块fork()实现多进程:
multiprocessing模块Process实现多进程:
1.为单独的入口函数开辟单独进程
2.自定义进程类,run定义启动函数,可以将共同使用的数据封装为类实例变量
多线程 multiprocessing模块Tread实现多进程:
1.与Process进程模块使用方法相同
2.注意区别python线程和进程的区别
IO多路复用 IO多路复用适合处理IO请求密集型问题,对于长期占用服务处理逻辑需要用多进程/线程
select–rs,ws,xs=select(rlist,wlist,xlist) rlist监听读属性IO,连接结束删除监听对象
poll—fdmap存放文件描述符与IO对象字典,register添加监听对象
epoll-- 与poll使用方法相同,但内部实现机制不同,epoll效率最高,可设置边缘触发
网络传输方法—TCP

使用TCP网络通信方式,特点是无丢失,无失序,无差错,无重复

技术细节
细节 实现
注册信息 用户名,密码
历史记录 用户名,查询单词,查询时间----数据库查询最近10条记录:时间排序
密码 暗文输入:getpass模块getpass([prompt])
存储加密:hashlib模块中的MD5加盐加密
# MD5加密算法调用
hash=hashlib.md5("salt**@来干小日本!".encode()) # 参数为加盐内容,可缺省
password="123456"
hash.update(password.encode())
secret=hash.hexdigest()
数据库设计
table
table
table
database dict
words
user
history
id int primary key auto_increment
word valchar <32>
explain valchar 200
id int primary key auto_increment
name valchar 32
password valchar 128 加密
id int primary key auto_increment
name valchar 32
time datetime defalult now
模块设计
整体概述

整体设计使用类实现封装。客户端模块实现用户交互interface,负责用户输入,结果呈现等基本功能;服务器模块采用多进程并发处理客户端连接请求;数据库模块处理数据读写,包括加码处理等;

客户端模块- client
class OnlineDictClient(): def __init__(self):  # 客户端连接套接字初始化def mian(self):      # 登录注册(一级界面)def regist(self):         # 用户注册 def login(self):          # 用户登录def dict(self,name):  # 主要功能界面:查询,历史记录(二级界面)   def search(self,name):    # 查询   def history(self,name):   # 历史记录查看
服务端模块- server
class OnlineDictServer():def __init__(self): # 数据库对象,监听套接字初始化def main(self):     # 循环监听,分配子进程def handle(self,client): # 子进程处理主逻辑,解析客户端请求内容def regist(self, client,request):     # 用户注册逻辑处理def login(self,client,info_log):      # 用户登录逻辑处理def search(self,client,request):    # 用户查询字典逻辑处理def history(self,client,request):       # 用户查看历史记录逻辑处理
数据库操作模块- db_operate
import pymysql,hashlib
class DataBase():def __init__(self):  # 初始化,连接数据库def secret(self,pwd):               # 密码加密,hashlib模块MD5处理密码def register(self, name, pwd):# 用户注册,数据库写操作-->table user:name password def login(self,name,pwd):     # 用户登录,数据库读操作<--select from user  def search(self,name,word):   # 用户查询,读单词解释<--select words:explain   def inserthistory(self,name,word):  # 用户查询记录写入,name,word和time-->historydef history(self,name):       # 历史记录查看,返回最近10条记录<--select+order by+limit 10

完整代码

客户端(client.py)

from socket import *
import pymysql
from getpass import getpass
import sysclass OnlineDictClient():# 客户端连接套接字初始化def __init__(self):self.ADDR=("127.0.0.1",5200) #服务器地址self.socketclient=socket()self.socketclient.connect(self.ADDR)# 登录注册(一级界面)def mian(self):while True:print("""=======Online Dict=======1.注册 2.登录 3.退出=========================""")cmd=input("输入选项:")if cmd not in ("1","2","3"):print("请输入正确选项!")continue# 直接将选项作为请求格式,避免再次拟定发送格式if cmd=="1": # 注册self.regist()elif cmd=="2": # 登录self.login()elif cmd=="3": # 退出sys.exit("谢谢使用!")# 用户注册def regist(self):while True:name=input("请输入名称:")# pwd=input("请输入密码:")# pwdc=input("请再次确认密码:")pwd=getpass()pwdc=getpass("Again:")if pwd!=pwdc:print("输入密码不一致")continueif " " in name or " " in pwd:print("输入用户名或密码不合法,包含空格")continues="R %s %s"%(name,pwd)self.socketclient.send(s.encode())confirm=self.socketclient.recv(1024)if confirm==b"OK":print("注册成功")breakelse:print("注册失败,用户名已存在!")# 用户登录def login(self):while True:print("""=======Online Dict=======用户登录界面=========================""")name = input("请输入您的名称:")pwd = input("请输入您的密码:")s="L %s %s"%(name,pwd)self.socketclient.send(s.encode())info_cfrm=self.socketclient.recv(1024)if info_cfrm==b"OK":print("恭喜登陆成功!")self.dict(name)breakelse:print("用户名或密码错误,请重新输入!")# 主要功能界面:查询,历史记录(二级界面)def dict(self,name):while True:print("""=======Online Dict=======1.英语单词查询2.历史记录查看3.注销=========================""")cmd=input("请输入选项:")if cmd == "1":  # 查询self.search(name)elif cmd == "2":  # 历史记录self.history(name)elif cmd == "3":  # 退出return# 查询def search(self,name):self.socketclient.send(("S %s"%name).encode())while True:word =input("请输入查询单词:")if not word:self.socketclient.send(b"EXIT")breakself.socketclient.send(word.encode())explain=self.socketclient.recv(1024)if explain==b"404":print("无此单词")else:print(explain.decode())# 历史记录查看def history(self,name):self.socketclient.send(("H %s"%name).encode())history=self.socketclient.recv(2048)print("您的历史记录:\n",history.decode())
if __name__=="__main__":client=OnlineDictClient()client.mian()

服务器(server.py)

from socket import *
import pymysql
from multiprocessing import *
from signal import *
from db_operate import  *
import sys
class OnlineDictServer():# 数据库对象,监听套接字初始化def __init__(self):# 数据库对象调用self.db=DataBase()# 套接字初始化self.port=5200self.ip="127.0.0.1"self.ADDR=(self.ip,self.port) #服务器地址self.socketfd=socket()self.socketfd.bind(self.ADDR)self.socketfd.listen(5)print("Listen from port:%d"%self.port)self.socketfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)signal(SIGCHLD,SIG_IGN)# 循环监听,分配子进程def main(self):print("")while True:try:conn,addr=self.socketfd.accept()print("connect from",addr)except Exception:print("服务器退出!")self.p=Handle(conn,self.db)self.p.start()
class Handle(Process):def __init__(self,conn,db):self.conn=connself.db=dbsuper().__init__()# 子进程处理主逻辑,解析客户端请求内容def run(self):while True:request=self.conn.recv(1024).decode()if not request or request[0]=="E":sys.exit(0)elif request[0] == "R":self.regist(request)elif request[0] == "L":self.login(request)elif request[0]=="S":self.search(request)elif request[0] == "H":self.history(request)# 用户注册逻辑处理def regist(self, request):name=request.split(" ")[1]pwd=request.split(" ")[-1]if self.db.register(name,pwd):self.conn.send(b"OK")else:self.conn.send(b"name exist")# 用户登录逻辑处理def login(self,info_log):name = info_log.split(" ")[1]pwd = info_log.split(" ")[-1]if self.db.login(name,pwd):self.conn.send(b"OK")else:self.conn.send(b"incorrect")# 用户查询字典逻辑处理def search(self,request):name=request.split(" ")[-1]while True:word=self.conn.recv(1024).decode()if word=="EXIT":breakexplain=self.db.search(name,word)if explain:self.conn.send(explain.encode())else:self.conn.send(b"404")# 用户查看历史记录逻辑处理def history(self,request):name=request.split(" ")[-1]records=self.db.history(name)if records:self.conn.send(records.encode())else:self.conn.send(("%s have no search history"%name).encode())
if __name__=="__main__":server=OnlineDictServer()server.main()

数据库操作(dboperate.py)

import pymysql
import hashlib
class DataBase():# 初始化,连接数据库def __init__(self):self.db=pymysql.connect(host="localhost",port=3306,user="root",password="123456",database="dict",charset='utf8' )# 游标self.cur = self.db.cursor()# 密码加密,hashlib模块MD5处理密码def secret(self,pwd):hash=hashlib.md5("salt**来干小日本!".encode())hash.update(pwd.encode())return hash.hexdigest()# 用户注册,数据库写操作-->table user:name passworddef register(self, name, pwd):# 对密码进行加密处理pwd=self.secret(pwd)# 判断是否存在该用户名sql = "select name from user where name='%s';" % nameself.cur.execute(sql)if self.cur.fetchone():return False# 插入记录try:sql = "insert into user (name,password) values ('%s','%s')" % (name, pwd)self.cur.execute(sql)# 写操作self.db.commit()return Trueexcept:self.db.rollback()return False# 用户登录,数据库读操作<--select from userdef login(self,name,pwd):pwd = self.secret(pwd)sql="select * from user where name='%s' and password='%s'"%(name,pwd)self.cur.execute(sql)if self.cur.fetchone():return Trueelse:return False# 用户查询,插入查询name,word和time-->historydef inserthistory(self,name,word):sql="insert into history (name,word) values ('%s','%s')"%(name,word)try:self.cur.execute(sql)self.db.commit()except:self.db.rollback()# 用户查询,记录,读单词解释<--select words:explaindef search(self,name,word):self.inserthistory(name,word)sql = "select wordexplain from words where word='%s'" % wordself.cur.execute(sql)# 返回结果为元组explain=self.cur.fetchone()if explain:return explain[0]# 历史记录查看,返回最近10条记录def history(self,name):sql = "select * from history where name=%s order by searchtime desc limit 10"self.cur.execute(sql,[name])records=self.cur.fetchall()str_=""for record in records:str_+=(str(record)+"\n")return str_
if __name__=="__main__":db=DataBase()res=db.history("lei")print(res)

最清晰的逻辑教你使用多进程实现TCP套接字词典查询(多并发/cs架构/MySQL/完整代码)相关推荐

  1. Linux下套接字详解(五)----基于fork多进程的TCP套接字(阻塞/同步/并发)

    简介 一个简单的改进方案是在服务器端使用多线程(或多进程).多线程(或多进程)的目的是让每个连接都拥有独立的线程(或进程),这样任何一个连接的阻塞都不会影响其他的连接.具体使用多进程还是多线程,并没有 ...

  2. 套接字编程---2(TCP套接字编程的流程,TCP套接字编程中的接口函数,TCP套接字的实现,TCP套接字出现的问题,TCP套接字多进程版本,TCP套接字多线程版本)

    TCP模型创建流程图 TCP套接字编程中的接口 socket 函数 #include <sys/types.h> /* See NOTES */ #include <sys/sock ...

  3. 教你使用 SO_REUSEPORT 套接字选项提升服务性能

    前言 Linux 网络栈中有一个相对较新的特性--SO_REUSEPORT 套接字选项,可以使用它来提升你的服务性能. 图 1: 上面的服务是使用并行监听器来避免请求连接瓶颈,而下面的服务只使用一个监 ...

  4. Maven项目+MVC三层架构+Mysql+Tomcat+私教预约系统前后端(私教、用户、管理员)+可以用于学习SSM框架、javaweb、maven项目入门

    Maven项目+MVC三层架构+Mysql+Tomcat+私教预约系统前后端(私教.用户.管理员)+可以用于学习SSM框架.javaweb.maven项目入门 可以用于课程设计.毕业设计的知识点入门学 ...

  5. 《卡尔威特的教育》读书摘抄及相关感想2400字

    <卡尔威特的教育>读书摘抄及相关感想2400字: 世界上的绝大部分工作须先培训才能上岗,而"为人父母"这份工作似乎是人类本能使然,大多数父母没做过入职前的培训就懵懵懂 ...

  6. 计算机网络套接字编程实验-TCP多进程并发服务器程序与单进程客户端程序(简单回声)

    1.实验系列 ·Linux NAP-Linux网络应用编程系列 2.实验目的 ·理解多进程(Multiprocess)相关基本概念,理解父子进程之间的关系与差异,熟练掌握基于fork()的多进程编程模 ...

  7. Linux_套接字(C++_TCP回显服务器——多进程/线程池(生产者消费者模型)处理多链接请求)

    文章目录 1.多进程版本 服务端 启动服务端 客户端 启动客户端 本地测试 2.多线程版本 3.模板线程池版本 线程池代码: 设计任务Task.h 服务端代码 1.多进程版本 这里选择创建子进程,让子 ...

  8. 好玩的deep dream(清晰版,pytorch完整代码)

      本文给出pytorch完整代码实现deep dream,加入了图像金字塔处理和高斯平滑处理,使生成图更加清晰美观.文中还讨论了各种因素对生成图的影响. 1, 完整代码   Deep dream图是 ...

  9. 计算机考试遇到不会读的字,不会读的字怎么打 轻松几招教你怎样打不会读的字...

    之前有一篇"你会写火字吗"一文在网络中爆红,讲述的是随着我们队计算机依赖性不断增强,很多人已经开始忘记字怎么写了,就连一个最简单的"火"字都忘记了,引来众多网友 ...

  10. 【机器学习入门】(9) 逻辑回归算法:原理、精确率、召回率、实例应用(癌症病例预测)附python完整代码和数据集

    各位同学好,今天我和大家分享一下python机器学习中的逻辑回归算法.内容主要有: (1) 算法原理:(2) 精确率和召回率:(3) 实例应用--癌症病例预测. 文末有数据集和python完整代码 1 ...

最新文章

  1. Spring Data ElasticSearch示例--使用NativeSearchQuery查询
  2. boost::icl模块实现测试 shell 来分割区间图
  3. SpringMVC自定义拦截器与异常处理(自定义异常)
  4. Windows、Linux和MAC的CR, LF, CR/LF换行符
  5. 首次使用mysql_mysql-8.0.20-winx64_初次使用过程(Win7x64)
  6. gitlab和jenkins发布代码
  7. [tensorflow]tensorflow2.1.0使用内置方法进行培训和评估
  8. 从门户到搜索:谁为百度打工?
  9. Java流处理之转换编码的转换流
  10. 【经验分享】BMPR文件及其打开软件Balsamiq Wireframes的下载和安装
  11. 骑士旅行问题(骑士走棋盘)
  12. hibernate Criteria setProjection
  13. Android:adb卸载系统应用软技能
  14. Discuz!论坛运营之如何开启发帖回帖@会员功能
  15. Python3:numpy的简单使用4(矩阵间的操作,合并数组,分割数组,读取文件操作)
  16. 一道关于索引的使用和key_len的计算的面试题
  17. JAVA实现AES加密
  18. 女生宿舍-同名专辑《女生宿舍 Life Is Beautiful》
  19. 39-Figma-APP套样机方法
  20. slqite3库查询数据处理方式_C语言实现sqlite3数据库查询的基本方法

热门文章

  1. Java经典编程习题100例:第18例:编写程序,将一个数组中的元素倒排过来。例如原数组为1,2,3,4,5;则倒排后数组中的值
  2. 救救企鹅(字符串hash)
  3. 【C# 教程系列第 23 篇】什么是Json?
  4. SEMer必会:通过SEO思维为网站获取精准流量
  5. ceph 数据均衡调整
  6. java timer任务
  7. SAP FICO 会计科目/客户/供应商/公司代码(组)OB55创建工作清单满足报表查询需求
  8. 新插的内存条BIOS无法认到!
  9. 辽宁省劳动经济学校计算机专业,辽宁省劳动经济学校计算机与艺术系专业介绍...
  10. 学术圈都在关注的公众号有哪些?我们帮你一次性get