博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PYTHON2.day10
阅读量:6974 次
发布时间:2019-06-27

本文共 11364 字,大约阅读时间需要 37 分钟。

前情回顾

1. 多线程并发网络模型

2. 基于Process的多进程并发网络
3. 集成模块socketserver完成网络并发
4. HTTPServer v2.0:模块封装,多线程并发,请求解析
5. 协程基础 : 定义,原理,优缺点
6. 介绍greenlet,学习gevent
      【1】 gevent.spawn()  生成协程对象
      【2】 gevent.joinall()  阻塞等待协程执行完成
      【3】 gevent.sleep()  提供gevent阻塞

*********************************************************

一. gevent模块(续)

  1. 动机:在gevent协程中,协程只有遇到gevent指定类型的阻塞才能跳转到其他协程,因此,我们希望将普通的IO阻塞行为转换为可以触发gevent协程跳转的阻塞,以提高执行效率。

    2. 转换方法:gevent 提供了一个脚本程序monkey,可以修改底层解释IO阻塞的行为,将很多普通阻塞转换为gevent阻塞。

  
        【1】 导入monkey
                from gevent  import monkey

         【2】 运行相应的脚本,例如转换socket中所有阻塞

                      monkey.patch_socket()
            
          【3】 如果将所有可转换的IO阻塞全部转换则运行all
                monkey.patch_all()
            
          【4】 注意:脚本运行函数需要在对应模块导入前执行

1 import gevent  2 from gevent import monkey  3 monkey.patch_all()#执行脚本插件,修改IO阻塞行为  4 from socket import *  5   6 #创建套接字  7 def server():  8     s = socket()  9     s.bind(('0.0.0.0',8888)) 10     s.listen(10) 11     while True: 12         c,addr = s.accept()#主程序遇到阻塞触发协程 13         print("Conect from",addr)#打印客户端 14         # handle(c)#处理客户端请求 15         gevent.spawn(handle,c)#把函数变成协程,c->不定参数}-----协程方案,多客户端 16  17 def handle(c): 18     while True: 19         data = c.recv(1024)#协程阻塞在recv 20         if not data: 21             break 22         print(data.decode()) 23         c.send(b"OK") 24  25 server() 26
gevent_server.py
1 from socket import *  2   3 #创套接字  4 sockfd = socket()  5   6 #发起连接  7 server_addr = ('172.40.71.149',8888)  8 sockfd.connect(server_addr)  9  10 #收发消息 11 while  True: 12     data = input(">>") 13     if not data: 14         break 15     sockfd.send(data.encode()) 16     data = sockfd.recv(1024) 17     print("From server:",data.decode()) 18  19 #关闭套接子 20 sockfd.close() 21
tcp_clent.py

二. 网络电子词典

  1. 功能说明

      【1】用户可以登录和注册
             * 登录凭借用户名和密码登录
                 * 注册要求用户必须填写用户名,密码,其他内容自定
                 * 用户名要求不能重复
                 * 要求用户信息能够长期保存
        
        【2】可以通过基本的图形界面print以提示客户端输入。
             * 程序分为服务端和客户端两部分
                 * 客户端通过print打印简单界面输入命令发起请求
                 * 服务端主要负责逻辑数据处理
                 * 启动服务端后应该能满足多个客户端同时操作
        
         【3】客户端启动后即进入一级界面,包含如下功能:
             
                  登录    注册    退出

                 * 退出后即退出该软件

                  * 登录成功即进入二级界面,失败回到一级界面
                  * 注册成功可以回到一级界面继续登录,也可以直接用注册用户进入二级界面
        
         【4】用户登录后进入二级界面,功能如下:
             
                  查单词    历史记录    注销

                 * 选择注销则回到一级界面

                  * 查单词:循环输入单词,得到单词解释,输入特殊符号退出单词查询状态
                  * 历史记录:查询当前用户的查词记录,要求记录包含name   word   time。可以查看所有记录或者前10条均可。
    
     2. 单词本说明

      【1】 特点 : 1. 每个单词一定占一行

                      2. 单词按照从小到大顺序排列
                                  3. 单词和解释之间一定有空格
        
         【2】 查词说明 : 1. 直接使用单词本查询(文本操作)
                                             2. 先将单词存入数据库,然后通过数据库查询。(数据库操作)
        
   3. 操作步骤
       
         【1】 确定并发方案? 确定套接字使用? 确定具体细节?
           使用文件查询还是数据库?
                    
                     * fork 多进程 ,tcp套接字
                     * 注册后回到一级界面,历史记录显示最近10条
                     * 文本直接查询

   

         【2】 建立数据库 : 建立几个表,表关系,表字段及类型
               * 想办法将单词导入数据库
                    
                     用户表 : id   name   passwd
                     历史记录:id   name   word    time
                     单词存储:id   word   mean

                    1. 创建数据库:

                       create database dict default charset=utf8;

                    2. 创建用户表:

                         create table user (id int primary key auto_increment,name varchar(32) not null,passwd varchar(16) default '000000');
          
                     3. 创建历史记录表:
                         create table hist (id int primary key auto_increment,name varchar(32) not null,word varchar(32) not null,time varchar(64));
                    
                     4. 创建单词表:
                         create table words (id int primary key auto_increment,word varchar(32),mean text);

         【3】 结构设计:即如何封装,客户端和服务端工作流程。具体项目有几个功能模块。

                    * 函数封装

                     * 客户端启动--》进入一级界面--》登录--》二级界面--》具体请求--》展示内容
                     * 服务端循环接收请求--》处理请求--》将数据发送给客户端
                     * 功能模块:登录,注册,查询单词,历史记录

         【4】 完成通信的搭建

        【5】 分析具体通能,逐个模块实现

            
          
                 1、注册
          客户端:*输入注册信息
                                          *将信息发送给服务端
                      *得到服务器反馈
          服务端:*接收请求
                      *判断是否允许注册
                      *反馈结果给客户端
                      *如果可以注册则插入数据库
       
                 2. 登录
                         客户端: * 输入用户名密码
                                          * 将信息发送给服务器
                                          * 得到服务端反馈
                                          * 如果登录成功进入二级界面
                        
                         服务端: * 接收请求
                                          * 判断是否允许登录
                                          * 反馈结果

                3. 查词

                     客户端 : * 输入查询单词
                                             * 发送请求给服务端
                                             * 获取结果
                        
                         服务端 : * 接收请求
                                             * 查找单词
                                             * 将查询结果发送给客户端
                                             * 插入历史记录

                4. 历史记录

1 import pymysql  2   3 f = open('dict.txt')  4 db = pymysql.connect('localhost','root','123456','dict')  5   6 cursor = db.cursor() #创建游标  7   8 for line in f:  9     tmp = line.split(' ') 10     world = tmp[0] 11     mean = ' '.join(tmp[1:]).strip() 12     sql='insert into worlds (world,mean) values ("%s","%s")'%(world,mean) 13  14     try: 15         cursor.execute(sql) 16         db.commit() 17     except Exception: 18         db.rollback() 19 f.close()
worlds_dict.py
1 '''  2 dict project for AID  3 '''  4 from socket import *  5 import pymysql  6 import os,sys  7 import time#处理沾包  8 import signal#处理僵尸  9  10 #定义全局变量 11 if len(sys.argv)<3: 12     print('''Start as: 13         python3 dict_server.py 0.0.0.0 8000 14         ''') 15     sys.exit(0) 16  17 HOST = sys.argv[1] 18 PORT = int(sys.argv[2]) 19 ADDR = (HOST,PORT) 20 DICT_TEXT = "./dict.txt" 21  22 #搭建网络连接 23 def main(): 24     #连接数据库 25     db = pymysql.connect('localhost','root','123456','dict') 26     #创建套接字 27     s = socket() 28     # s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) 29     s.bind(ADDR) 30     s.listen(5) 31  32  33     #僵尸进程处理 34     signal.signal(signal.SIGCHLD,signal.SIG_IGN) 35  36  37     while True: 38         try: 39             c,addr = s.accept() 40             print("Connect from",addr) 41         except KeyboardInterrupt: 42             s.close() 43             sys.exit("服务器退出") 44         except Exception as e: 45             print(e) 46             continue 47  48         #创建子进程 49         pid = os.fork() 50         if pid ==0: 51             s.close() 52             do_child(c,db) 53             sys.exit() 54         else: 55             c.close() 56  57  58  59  60  61 #处理客户端请求 62 def do_child(c,db): 63     while True: 64         #接收客户端请求 65         data = c.recv(1024).decode() 66         print(c.getpeername(),':',data) 67         if not data or data[0]=="E": 68             c.close() 69             sys.exit() 70         elif data[0]=='R': 71             do_register(c,db,data) 72         elif data[0]=='L': 73             do_login(c,db,data) 74         elif data[0]=='Q': 75             do_query(c,db,data) 76         elif data[0]=='H': 77             do_hist(c,db,data) 78  79  80  81  82  83  84 def do_register(c,db,data): 85     l = data.split(' ') 86     name =l[1] 87     passwd = l[2] 88     cursor = db.cursor() 89  90     sql ="select * from user where name='%s'"%name 91     cursor.execute(sql) 92     r = cursor.fetchone() 93     if r != None: 94         c.send(b'EXITS') 95         return 96  97     #插入用户 98     sql = "insert into user(name,passwd) values('%s','%s')"%(name,passwd) 99     try:100         cursor.execute(sql)101         db.commit()102         c.send(b'OK')103     except:104         db.rollback()105         c.send(b'FAIL')106 107 108 109 def do_login(c,db,data):110     l = data.split(' ')111     name = l[1]112     passwd = l[2]113     cursor = db.cursor()114 115 116     sql = "select * from user where name='%s' and passwd='%s'"%(name,passwd)117     #查询用户118     cursor.execute(sql)119     r = cursor.fetchone()120     if r ==None:121         c.send(b'FAIL')122     else:123         c.send(b'OK')124 125 126 127 128 129 def do_query(c,db,data):130     l = data.split(' ')131     name = l[1]132     world = l[2]133 134 135     #插入历史记录136     cursor = db.cursor()137     tm = time.ctime()138     sql = "insert into hist(name,world,time) values ('%s','%s','%s')"%(name,world,tm)139     try:140         cursor.execute(sql)141         db.commit()142     except:143         db.rollback()144 145     #单词本查找146     f = open(DICT_TEXT)147 148     for line in f:149         tmp = line.split(' ')[0]#获取单词150         if tmp > world:151             break152         elif tmp == world:153             c.send(line.encode())154             return155     c.send("没有找到该单词")156     f.close()157 158 159 def do_hist(c,db,data):160     name = data.split(' ')[1]161     cursor = db.cursor()162     sql = "select * from hist where name='%s' order by id desc limit 10"%name163     cursor.execute(sql)164     r = cursor.fetchall()165     if not r:166         c.send(b'FAIL')167         return168     else:169         c.send(b'OK')170         time.sleep(0.1)171     for i in r:172         msg = "%s  %s  %s"%(i[1],i[2],i[3])173         c.send(msg.encode())174         time.sleep(0.1)175     c.send(b'##')176 177 178 179 180 if __name__=="__main__":181     main()182
dict_server.py
1 from socket import *  2 import sys  3 import getpass  4   5 #创建网络连接  6 def main():  7     if len(sys.argv) <3:  8         print("argv is error")  9         return 10     HOST = sys.argv[1] 11     PORT = int(sys.argv[2]) 12     s = socket() 13     try: 14         s.connect((HOST,PORT)) 15     except Exception as e: 16         print(e) 17         return 18     while True: 19         print(''' 20             ===============================wecome============================== 21             --1.注册         2.登录        3.退出-- 22             ''') 23         try: 24             cmd = int(input("输入选项:")) 25         except Exception as e: 26             print("命令错误") 27             continue 28         if cmd not in [1,2,3]: 29             print("请输入正确选项") 30             continue 31         elif cmd ==1: 32             do_register(s) 33         elif cmd ==2: 34             do_login(s) 35         elif cmd ==3: 36             s.send(b'E') 37             sys.exit("谢谢使用") 38  39 def do_register(s): 40     while True: 41         name = input("User:") 42         passwd = getpass.getpass() 43         passwd1= getpass.getpass("Again:") 44  45         if (' 'in name) or (' ' in passwd): 46             print("用户名密码不能有空格") 47             continue 48         if passwd != passwd1: 49             print("两次密码不一致") 50             continue 51  52         msg = "R %s %s"%(name,passwd) 53         #发送请求 54         s.send(msg.encode()) 55         #等待回复 56         data = s.recv(128).decode() 57         if data =='OK': 58             print("注册成功") 59             # login(s,name)#注册成功进入二级界面 60         elif data =='EXISTS': 61             print("用户已存在") 62         else: 63             print("注册失败") 64         return 65  66  67  68 def do_login(s): 69     name = input("User:") 70     passwd = getpass.getpass() 71     msg = "L %s %s"%(name,passwd) 72     s.send(msg.encode()) 73     data = s.recv(128).decode() 74     if data =="OK": 75         print("登录成功") 76         login(s,name) 77     else: 78         print("登录失败") 79  80 def login(s,name): 81     while True: 82         print(''' 83             ===============================wecome============================== 84             --1.查词         2.历史记录        3.注销-- 85             ''') 86         try: 87             cmd = int(input("输入选项:")) 88         except Exception as e: 89             print("命令错误") 90             continue 91         if cmd not in [1,2,3]: 92             print("请输入正确选项") 93             continue 94         elif cmd ==1: 95             do_query(s,name) 96         elif cmd ==2: 97             do_hist(s,name) 98         elif cmd ==3: 99             return #回到一级界面100 101 def do_query(s,name):102     while True:103         world = input("单词:")104         if world == '##':105             break106         msg ='Q %s %s'%(name,world)107         s.send(msg.encode())108         #可能是单词解释.也可能是找不到109         data = s.recv(2048).decode()110         print(data)111 112 def do_hist(s,name):113     msg = "H %s"%name114     s.send(msg.encode())115     data = s.recv(128).decode()116     if data =="OK":117         while True:118             data = s.recv(1024).decode()119             if data =="##":120                 break121             print(data)122     else:123         print("没有历史记录")124 125 126 127 128 129 130 131 132 if __name__=="__main__":133     main()
dict_clent.py

cookie :
   1. 收集命令行参数为一个列表

       【1】 import sys

          【2】 sys.argv 可以将命令行输入参数收集为一个列表
          【3】 默认命令行以空格分隔每一项,如果一个整体中有空格则用引号注明一个整体
          【4】 收集的列表中所有项均为字符串

   2.使用getpass输入密码
   【1】import getpass
   【2】passwd=getpass.getpass(),其中getpass()函数用法与input相同,只是可以自动
     隐藏输入内容

作业 : 1. 整理进程线程网络内容
                 2. 复习mysql的理论内容和基本操作

转载于:https://www.cnblogs.com/shengjia/p/10439690.html

你可能感兴趣的文章
Groovy Closure简介
查看>>
扫盲 -- What's MOOC ?
查看>>
论文写作0
查看>>
C#构造函数
查看>>
关于数理统计学及其与概率论之间联系的一些理解
查看>>
心急的C小加
查看>>
freemaker的使用,记下以后看
查看>>
set nocount on的使用
查看>>
利用SQL Profiler 追踪数据库操作
查看>>
MYSQL数据库设计规范与原则
查看>>
[学习笔记]圆方树
查看>>
[NOI2017]泳池——概率DP+线性递推
查看>>
chrome贴吧插件——源代码
查看>>
还为代码编写愁吗?代码生成器将让你编写代码测试代码速度极大提升
查看>>
201621123048《Java程序设计》第六周学习总结
查看>>
java 查看线程死锁
查看>>
转: 理解Python的With语句
查看>>
看博客学学Android(十五)
查看>>
es6中class类的全方面理解(二)------继承
查看>>
c语言文件操作
查看>>