电子词典的python3 结合网络编程项目实例源码

此次为第一版的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()







你可能感兴趣的:(python)