电子词典项目

电子词典项目

1. 功能说明

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

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

  3. 能够满足多个用户同时登录操作的需求

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

  5. 用户登陆后即进入二级界面
    查单词 查看历史记录 退出
    单词本:每行一个单词
    单词和解释之间一定有空格
    后面的单词一定比前面的大

    查单词:输入单词,显示单词意思,可以循环查询。
    输入##表示退出查词
    查看历史记录:查看当前用户的历史查词记录
    name word time
    退出:表示退出到一级界面,相当于注销

2. 过程分析

  1. 确定技术点
    什么并发 进程线程
    什么套接字 流式套接字
    什么数据库 mysql
    文件处理还是数据库查询 数据库查询
    如果是数据库查询如何将单词存入数据库

  2. 建立数据表
    建立几个表
    每个表结构
    表关系
    3个表 用户信息 历史记录 存单词
    注册 查询历史记录 查单词
    登陆 查单词

  3. 项目分析
    仿照ftp和聊天室进行项目分析

  4. 搭建通信框架

  5. 分析有几个功能,如何封装,每个功能具体实现什么内容
    服务端:登陆 注册 查词 历史记录
    客户端:打印界面 发出请求 接受反馈 打印结果
    技术点:并发(多进程/多线程)
    套接字 tcp套接字
    数据库 mysql
    查词: 文本
    工作流程:创建数据库,存储数据
    搭建通信框架,建立并发关系
    实现具体功能封装

3.过程实现

  1. 创建数据库存储数据
    dict

    user: id name password
    hist: id name word time
    words:id word interpret

    创建数据库
    create database dict character set utf8;

    创建user表
    create table user(id int(10) primary key auto_increment,
    name varchar(32) not null,
    password varchar(16) default ‘000000’);

    创建hist表
    create table hist(id int auto_increment primary key,
    name varchar(32) not null,
    word varchar(32) not null,
    time varchar(64));

    创建words表
    create table words(id int auto_increment primary key,
    word varchar(32) not null,
    interpret text not null);

  2. 搭建基本框架

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

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

  3. 功能实现
    注册
    客户端
    1.输入注册信息
    延伸:
    密码隐形输入
    import getpass
    password = getpass.getpass()
    功能:隐藏密码输入
    2.将注册信息发送给服务器
    3.得到服务器反馈

    服务端
    1.接收请求
    2.判断是否允许注册
    3.将结果反馈给客户端
    4.注册信息插入数据库

    登录
    客户端
    1. 输入登录信息
    2. 将用户信息发送给服务器
    3. 得到服务器的反馈
    4. 跳转到二级界面
    服务端
    1. 接收请求
    2. 判断用户名是否存在
    3. 将结果反馈给客户端

    查词
    客户端
    1. 输入要查询的单词
    2. 将要查询的单词发送给服务器
    3. 得到服务器的反馈
    4. 打印得到的反馈
    服务端
    1. 接收客户端的信息
    2. 查询客户端要查询的单词(文本查询)
    3. 将用户名和查询单词插入数据库的hist表
    4. 将查询结果返回给客户端

    查询历史记录
    客户端
    1. 给服务器发送消息
    2. 接收服务端信息
    3. 打印消息
    服务端
    1. 接收客户端信息
    2. 根据用户名查询数据库中该用户的历史信息
    3. 给结果反馈给客户端

    退出
    客户端
    1. 给服务端发送信息
    2. 确认退出
    服务端
    1. 接收客户端发来的消息
    2. 关闭套接字

简易项目流程图

服务端代码

# dict_server.py
'''
name: lsm
date: 2018-9-28
email: 1356844759@qq.com
modules: pymysql
'''
from socket import *
import signal
import os
import time
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)
    print('Listen the port 8000....')

    while True:
        try:
            c, addr = s.accept()
        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(1024).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]
    password = l[2]
    cursor = db.cursor()
    print(name, password)
    sql = "select * from user where name = '%s' and password = '%s'" % (
        name, password)

    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]
    password = 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,password) values ('%s','%s')" % (
        name, password)
    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()

客户端代码


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])
    ADDR = (HOST, PORT)  # 服务器地址

    s = socket()
    try:
        s.connect((HOST, PORT))
    except Exception as e:
        print(e)
        return

    while True:
        print("================Welcome=================")
        print('** 1.注册  2. 登录  3. 退出  **')
        print("========================================")

        try:
            cmd = int(input('请输入选项>>'))
        except Exception as e:
            print(e)
        if cmd not in [1, 2, 3]:
            print('请输入正确选项!!!')
            # 清除标准输入
            sys.stdin.flush()
            continue
        elif cmd == 1:
            name = do_register(s)
            if name:
                print('注册成功')
                login(s, )
            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')
            sys.exit("谢谢使用")



def do_register(s):
    while True:
        name = input("User:")
        password = getpass.getpass()
        password1 = getpass.getpass("Agin:")

        if (' ' in name) or (' ' in password):
            print('用户名和密码不允许有空格')
            continue
        if password != password1:
            print('两次密码不一致')
            continue

        msg = 'R {} {}'.format(name, password)
        # 发送请求
        s.send(msg.encode())

        # 等待回复
        data = s.recv(128).decode()
        if data == 'OK':
            return name
        elif data == 'EXISTS':
            return 1
        else:
            return 2


def do_login(s):
    name = input("User:")
    password = getpass.getpass()
    msg = 'L {} {}'.format(name, password)
    s.send(msg.encode())
    data = s.recv(128).decode()

    if data == 'OK':
        return name
    else:
        return

def login(s, name):
    while True:
        print("================查询界面=================")
        print('** 1.查词  2. 历史记录  3. 退出  **')
        print("========================================")

        try:
            cmd = int(input('请输入选项>>'))
        except Exception as e:
            print(e)
        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()

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值