day10-并发编程&数据库基础

Day10 并发编程&数据库基础

1 内容回顾

# 网络编程
    # 1.概念
        # osi五层协议
            # 应用层
            # 传输层
                # tcp 面向连接通信,并且数据之间无边界,可靠
                    # 先建立连接 : 三次握手
                    # 基于连接通信 :每一条信息都有回执
                        # 粘包现象
                            # struct模块自定义协议解决
                    # 断开连接 :  四次挥手
                # udp 不需要提前建立链接,数据之间有边界,不可靠-
                    # 不需要建立\断开连接
                    # 只要知道对方的ip和端口直接发送信息就可以
            # 网络层
            # 数据链路层
            # 物理层
    # 2.代码
        # socket
        # osi5层协议除了应用层之外其他基层的抽象层
        
# tcp-server
import socket
sk = socket.socket()
sk.bind(('192.168.12.1',9001))
sk.listen()

conn,addr = sk.accept()   # 接受客户端请求建立连接 -- 三次握手
conn.send(msg)     # msg必须是字节类型
message = conn.recv(n)    # n是接受消息的最大字节数
conn.close()       # 关闭了和某一个客户端的连接 -- 四次挥手

sk.close()         # 关闭了整个网络服务

# tcp-client-+
import socket
sk = socket.socket()
sk.connect(('192.168.12.1',9001))  #  三次握手
message = sk.recv(n)
sk.send(msg)
sk.close()

# udp-server
import socket
socket.socket(type = socket.SOCK_DGRAM)

from socket import socket,SOCK_DGRAM
sk = socket(type=SOCK_DGRAM)
sk.bind(('127.0.0.1',9002))

msg,client_addr = sk.recvfrom(n)
sk.sendto(消息,client_addr)

sk.close()


# udp-client
import socket
sk = socket.socket(type = socket.SOCK_DGRAM)
sk.sendto(msg,('127.0.0.1',9002))
msg,server_addr = sk.recvfrom(n)
sk.close()

# socketserver
import socketserver

class Myserver(socketserver.BaseRequestHandler):
    def handle(self):
        conn = self.request

server = socketserver.ThreadingTCPServer(Myserver,('127.0.0.1',9000))
server.serve_forever()

2 今日内容

# 并发编程
    # 概念 : 面试\未来做架构相关也会用
    # 有少量的代码

    # 并发的概念
    # 进程
    # 线程 : GIL锁 由操作系统控制 对于IO的感知能力非常强
    # 协程 : 由程序控制的 对于IO操作的敏感度相对低 只有和网络相关的阻塞能够被协程感知到
# mysql数据库
    # 程序员对数据库的基础操作

# 只要有io,程序就会阻塞

3 并发编程

# input :
    # recv recvfrom input read load
# output:
    # send sendto print write dump
# 输入输出是不占用CPU的
# 计算机是多少cpu : 4c 8c 16c
# 纯计算 :就是不涉及任何输入输出,单纯对内存中数据进行操作
# 只要涉及到输入输出都要占一大笔时间
    # 7200r : 7200转每分钟
    # 从硬盘上找到一个数据的时间 0.9ms = 0.0009s
    # 0.3s
# CPU指令的计算速度 500000000 = 5亿 每一秒钟可以执行5亿条指令
# 50000 * 9s = 45w
# 读一次硬盘的时间够CPU执行45w条指令了

# pycharm qq EV录屏 浏览器 飞秋 360 vnc 搜狗输入法
# n多程序同时工作在计算机中,这些程序都需要CPU处理
    # 1.CPU如何为超过本身个数的服务们提供服务
    # 2.服务于服务之间是怎么分配的内存
# 所有的程序在没执行起来之前叫程序\文件,执行起来之后叫进程
# 什么叫做进程process? 进行中的程序
# 每一个进程在运行的过程中会被分配一块属于他自己的内存,进程之间的内存隔离
# CPU在多个进程之间进行轮转执行进程的任务
# 如果两个进程在CPU上同时被执行 -- 并行
# 如果两个进程看起来是同时执行的,但实际上在一块儿CPU上轮流被执行 -- 并发

# 进程 : 内存的隔离
# 线程 : 具体代码的执行进度
# 协程

4 程序

import os
import time
from multiprocessing import Process
def func1():
    print(123,os.getpid())
    time.sleep(1)
    print(456)

def func2():
    print('aaa',os.getpid())
    time.sleep(1)
    print('bbb')
if __name__ == '__main__':
    Process(target=func1).start()
    Process(target=func2).start()

# func1()
# func2()

5 进程

# 进程是计算机中资源分配的最小单位
# 所有的计算机中的内存资源 文件资源 程序代码

# 进程可以被操作系统调度\CPU执行
# 一个进程在创建的时候 必须创建大量的资源内存资源 文件资源 程序代码
# 一个进程在结束的时候 必须被销毁
# 谁来销毁这个进程呢?
    # 一个进程总是被他的父进程销毁掉
# 进程与进程之间有一个父子关系
    # 父进程要负责销毁子进程
# 你在你写的python代码中开启的所有进程都是子进程
# 而你写的这个程序本身是这些子进程的父进程

import os
import time
from multiprocessing import Process

def func(参数1,参数2):
    print('一个子进程',os.getpid(),参数1,参数2)
    time.sleep(1)

if __name__ == '__main__':   # 当本文件被导入的时候不执行if条件中的代码
    p = Process(target=func,args=(1,2))
    p.start()
    p.join()   # 阻塞 等待子进程执行完毕
    print('子进程执行完啦')

import socket
from multiprocessing import Process
def func(conn):
    while True:
        conn.send(b'hello')     # msg必须是字节类型
        message = conn.recv(1024)    # n是接受消息的最大字节数
        print(message)

if __name__ == '__main__':
    sk = socket.socket()
    sk.bind(('127.0.0.1',9001))
    sk.listen()
    while True:
        conn,addr = sk.accept()   # 接受客户端请求建立连接 -- 三次握手
        Process(target=func,args=(conn,)).start()
    conn.close()

6 线程

# 创建一个进程是非常浪费时间 和 资源的
# 线程 -- 轻型进程
# 同一个进程之间的多个线程内存是共享的
# 线程的开启速度比进程快
# 线程也可以利用多核

# 正常的进程和线程之间的区别 :
    # 进程是 内存隔离的 占用的资源多
    # 线程之间 内存共享的 占用的资源少

# python的线程
    # cpython解释器下的多线程
    # 同一个进程下的多个线程不能被CPU同时执行
    # 多个线程中的IO操作仍然会被规避
# 大部分只要涉及到文件\网络的操作,多线程会更快
# 真正能够参与计算的不过就是那几个CPU
    # 规避IO操作,让IO操作的时间尽量的缩短
    # 或者尽量的复用这部分时间
import time
from urllib import request
from threading import Thread
url_lst = [
    'http://www.baidu.com',
    'http://www.sogou.com',
    'http://www.qq.com',
    'http://www.163.com',
    'http://www.taobao.com',
    'http://www.jd.com',
    'http://www.tmall.com',
    'http://www.cnblogs.com',
    'http://www.mi.com',
    'http://www.luffycity.com',
]
def get_url(url):
    ret = request.urlopen(url)  # 请求一个网页

start_t = time.time()
t_lst = []
for url in url_lst:   # 开启10个线程,每个线程个字去请求1个网页,即同时请求10个网页
    t = Thread(target=get_url,args=(url,))
    t.start()
    t_lst.append(t)
for t in t_lst:
    t.join()
print(time.time()-start_t)


start_t = time.time()
for url in url_lst:
    ret = request.urlopen(url)
print(time.time()-start_t)

# jython Python语言 最终是被JAVA解释器解释的 而java的解释器回收机制不是gc -- 不会受到全局解释器锁的影响
# pypy
# cpython 有一个全局解释器锁 GIL 是由于GC机制和解释型语言双重限制导致了必须要在解释器中加锁
         # 导致了在一个进程中不能有多个线程同时访问CPU
         # 虽然不能同时做计算会影响一些效率,但是绝大多部分情况下线程仍然能够非常好的提高程序的效率
        
        
"""   
import socket
from threading import Thread
def func(conn):
    while True:
        conn.send(b'hello')     # msg必须是字节类型
        message = conn.recv(1024)    # n是接受消息的最大字节数
        print(message)

if __name__ == '__main__':
    sk = socket.socket()
    sk.bind(('127.0.0.1',9001))
    sk.listen()
    while True:
        conn,addr = sk.accept()   # 接受客户端请求建立连接 -- 三次握手
        Thread(target=func,args=(conn,)).start()
    conn.close()
"""

7 协程

from gevent import socket
import gevent   # gevent在识别阻塞之后,会在遇到阻塞的时候自动识别

def func(conn):
    while True:
        conn.send(b'hello')     # msg必须是字节类型
        message = conn.recv(1024)    # n是接受消息的最大字节数
        print(message)

if __name__ == '__main__':
    sk = socket.socket()
    sk.bind(('127.0.0.1',9001))
    sk.listen()
    while True:
        conn,addr = sk.accept()
        gevent.spawn(func,conn)   # 开协程
    conn.close()

# 协程的好处 :可以开的个数更多
# 5 * 20 * 500 = 50000

8 数据库

# 安装数据库 server端

# 启动数据库
    # server端
    # net start mysql 启动服务端
    # net stop mysql  关闭服务端

# mysql客户端
    # 执行mysql.exe可以启动客户端,连接上server端

# mysql> select user();  # 查看当前登录的用户是谁
    # ;是sql语句的结束符,写任何代码之后都应该自己添加;表示一句指令的结束
# mysql> exit 表示退出客户端

# cmd命令行直接输入 mysql -u用户名 -p密码
# mysql -uroot -p123  表示以root用户登录 密码是123
# 设置密码 set password = password('新密码')

# mysql(开源 互联网公司) oracle(金融公司 事业单位) sqlserver db2 postgresql sqllite
# mongodb redis memcache hbase
# 名词
    # DBMS数据库管理系统
    # DBA数据库管理员
    # 什么是库 DB
    # 什么是表 table
    # 什么是数据 data

# 数据库的操作
    # 创建库 : create database; 数据库的名字
        # 相当于创建了一个文件夹
    # 查看库 : show databases;
    # 使用库 : use py27
        # 切换到对应的文件夹下
    # 查看当前库有哪些表 : show tables;
    # 删除库 : drop database py27;

# 数据表的操作
    # 创建表
        # 语法 create table 表名(字段名 类型(长度) 约束,字段名 类型(长度) 约束...);
        # create table score(id int(8),name char(20),num int(4)) charset=utf8;
    # 修改表
    # 查看表结构 :
                # desc score;                更直观
                # show create table score;   更全面: 查看表的编码 存储引擎
                # mysql5.6以上版本 默认innodb
                    # 支持事务
                    # 行级锁 表锁 数据修改频繁
                    # 外键约束
    # 删除表 : drop table 表名;
# 数据的操作
    # 增
        # insert into 表名(字段名) values (值);
        # insert into score(id,name,num) values (1,'alex',0);
        # insert into score values (2,'wusir',60);
        # insert into score values (2,'wusir',60),(2,'wusir',60),(2,'wusir',60);
        # insert into score(name,num) values ('松松',100);
        # insert into score(name,num) values ('松松',100),('立立',99);
    # 删
        # delete from 表名 where 条件;
        # delete from score where id = 2;
    # 改
        # update 表 set 字段名='新的值' where 条件
        # update score set id=4 where name = '松松'
    # 查
        # select * from 表

# 类型 和 约束
# 类型
    # 数字 :
        # 整型 :长度的约束都是无效的,它能够表示的大小只和它存储的字节数相关
            # 年龄 : tinyint 1bytes 不算符号最多可以存到255 算上符号127
            #  smallint 2bytes
            #  mediumint 3bytes
            # int 4bytes 2**32  整数
            # bigint 8字节 2**64
                # create table t1(age1 tinyint(2),age2 tinyint,age3 tinyint unsigned);
                # create table t1(age int unsigned);
        # 浮点型
            # float(m,n) 单精度
                # m 表示一共有多少位
                # n 表示小数部分占其中的多少
                # float(5,2)
                # create table t2(salary float(5,2))
            # double(m,n) 双精度  能够表示的小数点之后的位数更精准
            # 薪资
    # 字符串 :
        # char(255) : 用户名\密码\手机号\身份证号
            # char(20)定长存储
                # 存储 'alex                ' 浪费空间
                # 操作节省时间
        # varchar(65535) : 评论 微博 微信朋友圈 论坛
            # varchar(255)变长存储
                # 存储 'alex4'  节省空间
                # 更加浪费时间
        # create table t4(username char(20),password char(32))
    # 时间 :
        # datetime 年月日时分秒
            # 登陆时间
            # 修改时间
            # 出生日期
            # 跑步计时
        # date 年月日
            # 注册时间
        # time 时分秒
        # timestamp 时间戳4字节 1970-2038-xx-xx
        # year 年
        # create table t5(dt datetime,d date,t time,ts timestamp,y year);
        # create table t6(dt datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,d date,t time,ts timestamp,y year);
    # 单选和多选 : 性别 爱好
        # enum单选和set多选并去重
        # create table t7(gender enum('男','女'),hobby set('抽烟','喝酒','烫头','洗脚'));
        # insert into t7 values('男','抽烟')


# 约束
# 数据的查询
    # 单表查询
    # 连表查询
# html

9 ftp作业

功能实现版本一:

功能实现版本二:

server端

import hashlib
import json
import socket
import socketserver


class Myserver(socketserver.BaseRequestHandler):
    def handle(self):
        msg = self.request.recv(1024)
        str_msg = msg.decode('utf-8')
        print(str_msg)
        opt_dic = json.loads(str_msg)
        print(opt_dic)
        if opt_dic['operate'] == 'register':
            # 把密码按照自己的算法进行摘要
            md5 = hashlib.md5(opt_dic['username'].encode('utf-8'))
            md5.update(opt_dic['password'].encode('utf-8'))
            pwd = md5.hexdigest()
            print('--->', pwd)
            # 把用户名和密码写在userinfo文件中
            with open('userinfo', 'a', encoding='utf-8') as f:
                f.write('{}|{}'.format(opt_dic['username'], pwd))
        elif opt_dic['operate'] == 'login':
            # 把密码按照之前的规则进行加密
            md5 = hashlib.md5(opt_dic['username'].encode('utf-8'))
            md5.update(opt_dic['password'].encode('utf-8'))
            pwd = md5.hexdigest()
            print('--->', pwd)
            # 和文件中的用户密码进行逐行比对
            with open('userinfo', encoding='utf-8') as f:
                for line in f:
                    user, passwd = line.strip().split('|')
                    if opt_dic['username'] == user and pwd == passwd:
                        print('登录成功')
                        break
                else:
                    print('登录失败')


sk = socketserver.ThreadingTCPServer(('127.0.0.1', 9000), Myserver)
sk.serve_forever()

客户端

import json
import socket

def login(sk):
    usr = input('用户名:').strip()
    pwd = input('密码:').strip()
    if usr and pwd:
        d = {'username': usr, 'password': pwd, 'operate': 'login'}
        str_d = json.dumps(d)
        sk.send(str_d.encode('utf-8'))


def register(sk):
    usr = input('用户名:')
    pwd = input('密码:')
    pwd2 = input('再次确认密码:')
    if pwd == pwd2: # 发送明文密码到server端才开始加密
        d = {'username': usr, 'password': pwd, 'operate': 'register'}
        str_d = json.dumps(d)
        sk.send(str_d.encode('utf-8'))

# 登录/注册
opt_lst = [('登录', login), ('注册', register)]
sk = socket.socket()
sk.connect(('127.0.0.1', 9000))
for index, opt in enumerate(opt_lst, 1):
    print(index, opt[0])
num = int(input('输入选项序号:'))
func = opt_lst[num - 1][1]
func(sk)

优化后登录版本:

Server

import hashlib
import json
import socket
import socketserver


class Auth:
    @staticmethod
    def get_md5(opt_dic):
        md5 = hashlib.md5(opt_dic['username'].encode('utf-8'))
        md5.update(opt_dic['password'].encode('utf-8'))
        pwd = md5.hexdigest()
        return pwd

    @classmethod
    def login(cls, opt_dic):
        # 把密码按照之前的规则进行加密
        pwd = cls.get_md5(opt_dic)
        # 和文件中的用户密码进行逐行比对
        with open('userinfo', encoding='utf-8') as f:
            for line in f:
                user, passwd = line.strip().split('|')
                if opt_dic['username'] == user and pwd == passwd:
                    dic = {'operate': 'login', 'flag': True}
                    break
            else:
                dic = {'operate': 'login', 'flag': False}
        return dic

    @classmethod
    def register(cls, opt_dic):
        # 把密码按照自己的算法进行摘要
        pwd = cls.get_md5(opt_dic)
        # 把用户名和密码写在userinfo文件中
        with open('userinfo', 'a', encoding='utf-8') as f:
            f.write('{}|{}\n'.format(opt_dic['username'], pwd))
        dic = {'operate': 'register', 'flag': True}
        return dic


class Myserver(socketserver.BaseRequestHandler):
    def mysend(self, dic):
        str_d = json.dumps(dic)
        self.request.send(str_d.encode('utf-8'))

    def handle(self):
        msg = self.request.recv(1024)
        str_msg = msg.decode('utf-8')
        opt_dic = json.loads(str_msg)
        if hasattr(Auth, opt_dic['operate']):
            dic = getattr(Auth, opt_dic['operate'])(opt_dic)
            self.mysend(dic)


sk = socketserver.ThreadingTCPServer(('127.0.0.1', 9000), Myserver)
sk.serve_forever()

Client:

import json
import socket


def send_dic(sk, dic):
    str_d = json.dumps(dic)
    sk.send(str_d.encode('utf-8'))

def recv_dic(sk):
    str_dic = sk.recv(1024).decode('utf-8')
    res_dic = json.loads(str_dic)
    return res_dic


def get_user(opt='login'):
    d = {}
    usr = input('用户名:').strip()
    pwd = input('密码:').strip()
    if usr and pwd and opt == 'register':
        pwd2 = input('密码确认:').strip()
        if pwd == pwd2:
            d = {'username': usr, 'password': pwd, 'operate': opt}
    elif usr and pwd:
        d = {'username': usr, 'password': pwd, 'operate': opt}
    return d


def login(sk):
    d = get_user()
    if d: send_dic(sk, d)
    res_dic = recv_dic(sk)
    if res_dic['operate'] == 'login' and res_dic['flag'] == True:
        print('登录成功')
    else:
        print('登录失败')


def register(sk):
    d = get_user('register')
    if d: send_dic(sk, d)
    res_dic = recv_dic(sk)
    if res_dic['operate'] == 'register' and res_dic['flag'] == True:
        print('注册成功')
    else:
        print('注册失败')


# 登录/注册
opt_lst = [('登录', login), ('注册', register)]
sk = socket.socket()
sk.connect(('127.0.0.1', 9000))
for index, opt in enumerate(opt_lst, 1):
    print(index, opt[0])
num = int(input('输入选项序号:'))
func = opt_lst[num - 1][1]
func(sk)

上传下载功能:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值