使用Python实现电子词典

项目内容:

一、功能说明:

1.用户可以登录和注册
	登录凭借用户名密码即可
	注册要求用户必须填写用户名和密码其他内容可自定
	用户名要求不能够重复

2.用户数据要求使用数据库长期保存
	数据表自定 

3.能够满足多个用户同时登陆操作的需求(多进程多线程)

4.功能分为客户端和服务端,客户端主要发起请求,服务端处理请求,用户启动客户端即进入一级界面
	一级界面的功能有:登陆、注册、退出

5.用户登陆后即进入二级界面
	二级界面内容有:查单词  查看历史记录 退出
	dict.txt--》每行一个单词
				单词和解释之间一定有空格
				后面的单词一定比前面的大
	查单词:输入单词,显示单词意思,可以循环查询,输入##表示退出查词
	查看历史记录:查看当前用户的历史查词记录
	name  word  time
	退出:退出到一级界面,相当于注销

二、项目分析

	1.确定技术点
		什么并发,什么套接字,什么数据库,
		文件处理还是数据库查询,如果是数据库查询如何将单词存入数据库
		
	2.建立数据表
		建立几个表  每个表结构  表关系
				3   		用户信息    历史记录        存单词

							注册	   查询历史记录	  查单词
							登录	   查单词

	3.项目分析
		服务器 : 登录  注册   查词   历史记录
		客户端 : 打印界面   发出请求    接收反馈   打印结果
		技术点 :   并发   sys.fork
       	套接字  tcp 套接字
  	    数据库  mysql
   	    查词    文本
   	    
	4.搭建通信框架
		工作流程: 创建数据库,存储数据 ---》 搭建通信框架,            
	 		      建立并发关系---》实现具体功能封装

三、实现

 1.创建数据库(使用mysql数据库)

mysql> create database dict default charset=utf8;
mysql> use dict;
Database changed
// 用户信息表
mysql> create table user(
    -> id int primary key auto_increment,
    -> name varchar(32) not null,
    -> passwd varchar(16) default '000000');
//历史记录表
mysql> create table hist(
    -> id int primary key auto_increment,
    -> name varchar(32) not null,
    -> word varchar(32) not null,
    -> time varchar(64));
//单词表
//text类型是文本类型,相当于字符串一种,比字符串大
mysql> create table words(
    -> id int primary key auto_increment,
    -> word varchar(32) not null,
    -> interpret text not null);

2.搭建基本框架

服务器	创建套接字 --> 创建父子进程 --> 子进程等待处理客户端请求 
	--> 父进程继续接收下一个客户端连接

客户端	创建套接字 --> 发起连接请求 --> 进入一级界面 --> 请求(登录,注册,退出)
	--> 登录成功进入二级界面 --> 请求(查词,历史记录)

3.功能实现:
	
	(1)注册
		客户端:
			1.输入注册信息
			cookie
			getpass模块:可以隐藏密码
			getpass.getpass()
			2.将注册信息发送给服务器
			3.得到服务器反馈
		服务端:
			1.接收请求
			2.判断是否允许注册
			3.将结果反馈给客户端
			4.注册信息插入数据库

	(2)登录
		客户端:
			1.输入登录信息
			2.将登录信息发送给服务器
			3.得到服务器的反馈
		服务端:
			1.接收请求
			2.判断是否可以登录
			3.将结果反馈给客户端

	(3)查单词
		客户端:
			1.输入单词
			2.将单词传给服务器
			3.得到服务器的反馈

		服务端:
			1.接收请求
			2.判断是否存在这个单词
			3.将结果反馈给客户端
			4.将查询的信息插入到数据库

	(4)查找历史记录
		客户端:
			1.发送请求
			2.将请求传给服务器
			3.得到服务器的反馈
		服务端:
			1.接收请求
			2.判断该用户是否存在历史记录
			3.将结果反馈给客户端

四、代码
1.将本地文件dict.txt中的单词信息添加到数据库

import pymysql
import re

f = open('dict.txt')
db = pymysql.connect("localhost", "root", "123456", "dict")
cursor = db.cursor()

for line in f:
    L = re.split(r"\s\s\s+", line)
    word = L[0]
    interpret = ' '.join(L[1:])
    sql = "insert into words (word,interpret) values('%s','%s')" % (word, interpret)
    try:
        cursor.execute(sql)
        db.commit()
    except Exception:
        db.rollback()
f.close()

2.客户端实现功能

 #!/usr/bin/python
# coding=utf-8
from socket import *
import sys
import getpass


#二级登录界面
def login(s, name):
	 while True:
    		print('''
        		==========查询界面============
       		    --1.查询  2.历史记录  3.退出--
        		==============================
       			 ''')

    		try:
        		cmd = int(input("输入选项>>"))
    		except Exception:
       		    print("命令错误")
        	   continue

		    if cmd not in [1, 2, 3]:
        		print("请输入正确选项")
        		sys.stdin.flush()  # 清除标准输入
        		continue
    		elif cmd == 1:
       	 		do_query(s, name)
    		elif cmd == 2:
        		do_hist(s, name)
    		elif cmd == 3:
        		print("用户退出")
       		    return

#客户端-->查单词
def do_query(s, name):
while True:
    word = input("请输入要查找的单词:")
    if word == '##':
        break
    msg = 'Q {} {}'.format(name, word)
    s.send(msg.encode())
    data = s.recv(1024).decode()
    if data == 'OK':
        data = s.recv(2048).decode()
        print(data)
    else:
        print("没有查到该单词")

#客户端-->查询历史记录
def do_hist(s, name):
 	msg = 'H {}'.format(name)
    s.send(msg.encode())
    data = s.recv(128).decode()
    if data == 'OK':
    	while True:
        	data = s.recv(1024).decode()
        	if data == '##':
            	break
        print(data)
	else:
    	print("没有历史记录")

# 客户端-->登录
def do_login(s):
	name = input("User:")
	passwd = getpass.getpass()
	msg = 'L {} {}'.format(name, passwd)
	s.send(msg.encode())
	data = s.recv(1024).decode()
	if data == 'OK':
    	return name
	else:
    	return

# 客户端-->注册
def do_register(s):
	while True:
    	name = input("User:")
    	passwd = getpass.getpass()
    	passwd1 = getpass.getpass('Again:')
    	if (' ' in name) or (' ' in passwd):
        	print("用户名和密码不允许有空格")
        	continue
    	if passwd != passwd1:
        	print("两次密码不一致")
        	continue
		msg = 'R {} {}'.format(name, passwd)
    	# 发送请求
    	s.send(msg.encode())
    	# 等待回复
    	data = s.recv(1024).decode()
    	if data == 'OK':
        	return name
   	    elif data == 'EXISTS':
       		 return 1
    	else:
        	return 2


# 创建网络连接
def main():
	if len(sys.argv) < 3:
   	 	print("argv is error")
    	return
	HOST = sys.argv[1]
	PORT = int(sys.argv[2])
	s = socket()
	try:
    	s.connect((HOST, PORT))
	except Exception as e:
    	print(e)
    	return

	while True:
    	print('''
        	==========Welcome=========
        	--1.注册  2.登录  3.退出--
        	==========================
        	''')
    	try:
        	cmd = int(input("输入选项>>"))
    	except Exception as e:
        	print("命令错误")
        	continue
    	if cmd not in [1, 2, 3]:
        	print("请输入正确选项")
        	sys.stdin.flush()  # 清除标准输入
    	elif cmd == 1:
        	name = do_register(s)
        	if name:
            	print("注册成功")
            	login(s, name)
        	elif name == 1:
            	print("用户存在")
        	else:
            	print("注册失败")
    	elif cmd == 2:
        	name = do_login(s)
        	if name:
            	print("登录成功")
            	# 进入二级界面
            	login(s, name)
        	else:
            	print("用户名或密码不正确")
    	elif cmd == 3:
        	s.send(b'E')
        	s.close()
        	sys.exit("谢谢使用")
if __name__ == "__main__":
			 main()

3.服务端实现功能

'''
name:
date:
email:[email protected]
modules:python pymysql...
This is a dict project for AID
'''

from socket import *
import os
import sys
import time
import pymysql
import signal

# 定义需要的全局变量
DICT_TEXT = './dict.txt'  # 单词本的位置
HOST = '0.0.0.0'
PORT = 8000
ADDR = (HOST, PORT)

# 接收请求
def do_child(c, db):
	# 循环接收客户端请求
	while True:
    	data = c.recv(1024).decode()
    	print(c.getpeername(), ":", data)
    	if (not data) or data[0] == 'E':
        	c.close()
        	sys.exit("客户端退出")
    	elif data[0] == 'R':
        	do_register(c, db, data)
    	elif data[0] == 'L':
        	do_login(c, db, data)
    	elif data[0] == 'Q':
        	do_query(c, db, data)
    	elif data[0] == 'H':
        	do_hist(c, db, data)

#服务端-->登录
def do_login(c, db, data):
	print("登录操作")
	L = data.split(' ')
	name = L[1]
	passwd = L[2]
	cursor = db.cursor()
	sql = "select * from user where \
        name='%s' and passwd='%s'" % (name, passwd)
	cursor.execute(sql)
	r = cursor.fetchone()
	if r == None:
    	c.send(b'FALL')
    	return
	else:
    	print('%s登录成功' % name)
    	c.send(b'OK')

#服务端-->注册
def do_register(c, db, data):
	print("注册操作")
	L = data.split(' ')
	name = L[1]
	passwd = L[2]
	cursor = db.cursor()
	sql = "select * from user where name='%s'" % name
	cursor.execute(sql)
	r = cursor.fetchone()
	if r != None:
    	c.send(b'EXISTS')
   	 	return
	sql = "insert into user (name,passwd) values\
            ('%s','%s')" % (name, passwd)
	try:
    	cursor.execute(sql)
    	db.commit()
    	c.send(b'OK')
	except Exception:
    	db.rollback()
    	c.send(b'FALL')
	else:
    	print("%s注册成功" % name)

#服务端-->查单词
def do_query(c, db, data):
	print("查单词操作")
	L = data.split(' ')
	name = L[1]
	word = L[2]
	cursor = db.cursor()

	def insert_history():
    	tm = time.ctime()
    	sql = "insert into hist (name,word,time)\
        	values('%s', '%s', '%s')" % (name, word, tm)
    	try:
        	cursor.execute(sql)
        	db.commit()
    	except Exception:
        	db.rollback()

	sql = "select * from words where word='%s'" % word
	cursor.execute(sql)
	try:
    	f = open(DICT_TEXT)
	except Exception:
    	c.send(b'FALL')
    	return
	for line in f:
    	tmp = line.split(' ')[0]
    	if tmp > word:
        	c.send(b'FALL')
        	f.close()
        	return
    	elif tmp == word:
        	c.send(b'OK')
        	time.sleep(0.1)
        	c.send(line.encode())
        	f.close()
        	insert_history()
        	return
	c.send(b'FALL')
	f.close()

#服务端-->查询历史记录
def do_hist(c, db, data):
	print("历史记录")
	L = data.split(' ')
	name = L[1]
	cursor = db.cursor()
	sql = "select * from hist where name='%s'" % name
	cursor.execute(sql)
	r = cursor.fetchall()
	if not r:
    	c.send(b'FALL')
    	return
	else:
    	c.send(b'OK')
	for i in r:
    	time.sleep(0.1)
    	msg = "%s    %s    %s" % (i[1], i[2], i[3])
    	c.send(msg.encode())
	time.sleep(0.1)
	c.send(b'##')


# 流程控制
def main():
	# 创建数据库连接
	db = pymysql.connect("localhost", "root",  "123456", "dict")
	# 创建套接字
	s = socket()
	s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
	s.bind(ADDR)
	s.listen(5)

	# 忽略子进程信号
	signal.signal(signal.SIGCHLD, signal.SIG_IGN)

	while True:
    	try:
        	c, addr = s.accept()
        	print("Connect from", addr)
    	except KeyboardInterrupt:
        	s.close()
        	sys.exit("服务器退出")
    	except Exception as e:
        	print(e)
        	continue

    	# 创建子进程
    	pid = os.fork()
    	if pid == 0:
        	s.close()
        	# mysql自带锁
        	do_child(c, db)
    	else:
        	c.close()
        	continue
if __name__ == "__main__":
	main()

以上仅供参考~

猜你喜欢

转载自blog.csdn.net/xiao_xlm/article/details/82889080