项目分析
<--!服务器 : 登录 注册 查词 历史记录
客户端 : 打印界面 发出请求 接收反馈 打印结果
技术点 : 并发 sys.fork
套接字 tcp 套接字
数据库 mysql
查词 文本
工作流程: 创建数据库,存储数据 ---》 搭建通信框架, 建立并发关系---》实现具体功能封装
1. 创建数据库存储数据
dict
user : id name passwd
hist : id name word time
words : id word interpret
create database dict default charset=utf8;
create table user (id int primary key auto_increment,name varchar(32) not null,passwd varchar(16) default '000000');
create table hist(id int auto_increment primary key,name varchar(32) not null,word varchar(32) not null,time varchar(64));
create table words (id int auto_increment primary key,word varchar(32) not null,interpret text not null);
2. 搭建基本框架
服务器 创建套接字 ---》 创建父子进程 --》 子进程 等待处理客户单端请求--》父进程继续接收下 一个客户端连接
客户端 创建套接字 --》发起连接请求 --》一级界面 --》请求(登录,注册,退出)--》登录成功 进入二级界面--》请求(查词,历史记录)
3. 功能实现
注册
客户端
1. 输入注册信息
2. 将注册信息发送给服务器
3. 得到服务器反馈
服务端
1. 接收请求
2. 判断是否允许注册
3. 将结果反馈给客户端
4. 注册信息插入数据库
cookie
import getpass
passwd = getpass.getpass()
功能 : 隐藏密码输入-->
dict_client.py文件
#!/usr/bin/python3
#coding=utf-8
from socket import *
import sys
import getpass
#创建网络连接
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() #清除标准输入
continue
elif cmd == 1:
r = do_register(s)
if r == 0:
print("注册成功")
# login(s,name) #进入二级界面
elif r == 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')
sys.exit("谢谢使用")
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(128).decode()
if data == 'OK':
return 0
elif data == 'EXISTS':
return 1
else:
return 2
def do_login(s):
name = input("User:")
passwd = getpass.getpass()
msg = "L {} {}".format(name,passwd)
s.send(msg.encode())
data = s.recv(128).decode()
if data == 'OK':
return name
else:
return
def login(s,name):
while True:
print('''
==========查询界面==========
1.查词 2.历史记录 3.退出
===========================
''')
try:
cmd = int(input("输入选项>>"))
except Exception as e:
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:
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(128).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("没有历史记录")
if __name__ == '__main__':
main()
dict_insert.py文件
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+',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:
db.rollback()
f.close()
dict_server.py文件
'''
name : Tedu
date : 2018-10-1
email: xxx
modules: pymongo
This is a dict project for AID
'''
from socket import *
import os
import time
import signal
import pymysql
import sys
#定义需要的全局变量
DICT_TEXT = './dict.txt'
HOST = '0.0.0.0'
PORT = 8000
ADDR = (HOST,PORT)
#流程控制
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()
do_child(c,db)
else:
c.close()
continue
def do_child(c,db):
#循环接收客户端请求
while True:
data = c.recv(128).decode()
print(c.getpeername(),":",data)
if (not data) or data[0] == 'E':
c.close()
sys.exit(0)
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')
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:
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:
db.rollback()
#文本查询
try:
f = open(DICT_TEXT)
except:
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'##')
if __name__ == '__main__':
main()