项目内容:
一、功能说明:
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()
以上仅供参考~