此次为第一版的python3 电子词典查询词汇,后期会继续跟进程序的交互以及优化
客户端:
#2018.07.02 今天白天搞定#
#客户端 服务端之间的连接依靠套接字socket 进程并发
#后期的聊天界面 以及手写字体的识别 语音后可以转换成汉字
''' 功能主要满足:
1.客户端提交查词,登录,注册的需要
2.服务端根据客户端的请求注册来进行怕端
'''
import sys
from socket import *
import pymysql
def register(s):
while 1 :
#注册姓名 密码 跟数据库里面的信息进行比对,如果没有就进行添加,如果有就继续 这里先简化,先不进行信息空格特殊字符的不合法型的筛选
name=input('请输入主要注册的姓名:')
if not name:
return
passward=input('请输入要注册的密码')
msg='R {} {}'.format(name,passward)
s.send(msg.encode())#将用户的信息 姓名与密码发送给服务器进行匹配检查反馈是否可以注册的信息
#这里面的R 就是表示需要服务端识别的命令,传递过去后,进行按中间空格分隔
data=s.recv(128).decode()#转义 #这里接受下服务端的反馈信息
if data=="OK": #经过与数据库对比得到确认 输入的姓名和密码不重复,可以进行注册
print('注册成功')
else:
print('注册的用户名重复或出错')
return
def login(s,db): #登录界面的客户端
name=input('请输入用户的姓名:')
passward=input('请输入用户的密码:')
#跟数据库进行对比分析
msg='L {} {}'.format(name,passward)
s.send(msg.encode())
data=s.recv(1024).decode()
if data=="OK":
print('登陆成功,请选择操作命令')
while 1:
print('''
============== 选项 ===============
==============1.查词===============
==============2.历史记录===========
==============3.退出===============
''')
cmd=input('请输入执行的操作:')
if cmd=='1':
query(s)
elif cmd=='2':
history(s)
elif cmd=='3':
return#返回上一层界面
else:
print('输入有误请重新输入:')
def query(s):
word=input('请输入要查询的单词:')
#将要查询的单词发送给服务器进行数据库筛选
msg='Q {}'.format(word)
s.send(msg.encode())
data=s.recv(1024).decode() #用来接受服务端的ok反馈
if data=='OK':
data=s.recv(1024).decode()#用来接受服务端的返回信息
print('单词解释为:',data)
def history(s):
print('历史查询记录')#当前登录的这个人的查询记录,由于我们在执行这个命令的时候,
#用户还没有退出该系统,所以直接调用当时存入
#数据库中的单词即可
s.send(b'H')
data=s.recv(1024).decode()
if data=="OK":
while 1:
data=s.recv(1024).decode()
if not data: #这里面我看可不可以直接写空 实际测试是可以使用的
break
print(data)
else:
print('没有记录该用户的查询情况')
def main():
if len(sys.argv)<3:
print('IP接口输入有误')
ADDR=sys.argv[1]
PORT=int(sys.argv[2])
db=pymysql.connect('localhost','root','123456','dict1')
#tcp的客户端
s=socket()
try:
s.connect((ADDR,PORT))#连接服务端
print('连接成功')
except:
print('服务端连接有问题')
while 1: #需要循环往复的进行命令的执行
print(''' ============== 选项 ===============
==============1.注册===============
==============2.登录===============
==============3.退出===============
''')
try:
cmd=int(input('请输入需要服务端执行的命令:'))
except:
print('输入命令有错误:')
continue #回到while 循环的开始位置
if cmd==1:
register(s)
elif cmd==2:
login(s,db)
else:
sys.exit('谢谢使用ZH词典')
if __name__ == '__main__':
main()
***********************************************
************************************************
****************************************
服务端
from socket import *
import os
import signal
import pymysql
import time
def register(connfd,db,data): #这里面有一个问题就是data的数据是由套接字传递的,为什么我不能把data放在函数里面利用connfd再重新赋值?
#20180702 21:54主要是因为我们的connfd所服务的对象的是多个客户端,所以当你直接舍弃data而去调用connfd的时候,容易发生通信混乱
print('执行注册操作')
info=data.split(' ')#分割为了得到name passward
name=info[1] #name
passward=info[2] #passward
cursor=db.cursor()#创建数据库的游标对象
sql1="select name from user where name='%s'"%name
cursor.execute(sql1)#z执行sql语句
r=cursor.fetchone()#这里运用游标的fetchone 特性进行选取产生的游标结果返回对象的一个,这里因为设置l数据库的姓名的唯一性
print(r)#None
if r!=None:
connfd.send(b'EXISTS')#存在的话就返回客户端提醒,已经存在
return
sql = "insert into user (name,passward) values ('%s','%s')"%(name,passward)
cursor.execute(sql)
db.commit()
connfd.send(b'OK')
print("注册成功")
def login(connfd,db,data):
print('登录界面')
name=data.split(' ')[1]#分割得到名字
passward=data.split(' ')[2]#分割得到密码 #然后将接收到的客户端的信息跟数据库进行比对,查看是否符合登录要求
cursor=db.cursor()
sql="select * from user where name='%s' and passward='%s'"%(name,passward)
print('**********************')
cursor.execute(sql)
print('--------------------------')
r=cursor.fetchone()#判断是否含有该用户信息
print(r)
if r !=None:
connfd.send(b'OK')
return name
else:
connfd.send(b'FALL')
def do_child(connfd,db):
while 1:
#根据不同的命令进行不同库额胡端
data=connfd.recv(128).decode() #接受客户端的信息命令 ,这里我们用首字母的大写+命令的英文 ,在进行中间空格分隔处理 分别得到不同的信息
if data[0]=='R': #进行注册
register(connfd,db,data) #这里面的data 为什么不能这样去把data放在函数里面来执行 -----已经解决,本函数的看第一行代码
elif data[0]=='L': #登录词典的界面
name=login(connfd,db,data)#这里面我需要登录的字典的人员的姓名 函数返回的是全局变量都可以使用
elif data[0]=="Q":#查询单词
query(connfd,data,db,name)
elif data[0]=="H":#查询历史单词记录
history(connfd,name,db)
def query(connfd,data,db,name):
while 1:
word = data.split(' ')[1]#单词帅选出来
cursor=db.cursor()
#进行数据库的筛选工作
def insert_history():#把所查到的单词都存入到列表
print('进入到测试')
tm=time.ctime()
print('111111111')
sql="insert into history (name,word,time) values('%s','%s','%s')"%(name,word,tm)#元组单个元组
print('99999999999999999')
cursor.execute(sql)
print('*-*-*--*-*-*-**-*-*-*-*-*-*-**-')
db.commit()
sql="select * from words where word='%s'"%word
cursor.execute(sql)
print('++++++++++++++')
r=cursor.fetchone()
print('----------------------')
print(r)
if not r:
connfd.send(b'FALL')
return
else:
connfd.send(b'OK')
time.sleep(0.5)
#利用返回的值进行相应的确认姓名,只有在确认登录的条件下,其他的二级界面才能开展进行
msg='{} {}'.format(r[1],r[2])
connfd.send(msg.encode())
#吧刚才查到的单词进行存储到列表中来
print('111111111111111111111')
insert_history()
print('*-*-*-*-456789')
return
def history(connfd,name,db):
cursor=db.cursor()#创建调用数据库的文档信息
sql="select * from history where name='%s'"%name
cursor.execute(sql)#执行sql语句
r=cursor.fetchall()#取出所有满足条件的信息 以元组的形式返回((),())
if r !=None:
connfd.send(b"OK")
time.sleep(0.5)
for i in r:
msg="{} {} {}".format(i[1],i[2],i[3])
connfd.send(msg.encode())#发送信息给客户端
time.sleep(0.5)#防止粘包现象
time.sleep(0.5)
return
def main():#主控制流程
s=socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
HOST='127.0.0.1'
PORT=9999
ADDR=(HOST,PORT)
s.bind(ADDR)
s.listen(5)
signal.signal(signal.SIGCHLD,signal.SIG_IGN)
db=pymysql.connect('localhost','root','123456','dict1') #连接数据库
while 1: #循环接受客户端的请求 这里利用多进程来处理信息,子进程用来处理客户端的请求,父进程用来处理其他客户端的连接请求
print('等待连接......')
connfd,addr=s.accept() #等待客户端的连接
print('连接成功',addr)
pid=os.fork() #这里开始进行父子进程的分工
if pid<0:
print('创建父子进程失败,重新操作')
continue
elif pid==0: #处理客户端的请求 ,这里面由于客户端的有两层界面,而我们服务端不需要理睬,只需要识别命令符号,进行响应操作就行
s.close()
print('子进程开始执行')
do_child(connfd,db)#把套接字传进去进行传递信息
else:
connfd.close()
continue
if __name__ == '__main__':
main()