并发编程网络编程和数据库的基础操作 第二部分

网络编程之 osi七层模型和三次握手四次挥手 socket

# by luffycity.com
# 概念
    # 应用层 http https ssl smtp ftp
    # 传输层 tcp udp  端口信息  四层路由器 四层交换机
        # tcp
            # 可靠的 面向连接的 全双工的 流式传输 效率低
            # 三次握手和四次挥手
                # 三次握手
                    # 把图背下来 syn ack
                # 四次挥手
                    # 把图背下来 fin ack
            # 黏包 : (自定义协议)先发送数据的长度,再发送数据
        # udp 效率高 不可靠 无连接 基于数据包的传输 能够传输的数据的长度有限
    # 网络层     ipv4协议192.168.0.1    ipv6协议 ff2312:f5242:12:1:1:1   网关地址 子网掩码 路由器 三层交换机
    # 数据链路层 mac地址 arp(通过ip地址找mac地址),rarp(通过mac地址找ip地址) 网卡  交换机
    # 物理层


# 1.评论  限制长度   数据库的carchar(255)
# 2.即时聊天的工具   udp

# socket
# socketserver

# 手写socket
# server - tcp
import socket
# sk = socket.socket()
# sk.bind(('127.0.0.1',9000))
# sk.listen()
#
# # while True表示能够和多个client通信
# conn,addr = sk.accept()  # 建立三次握手的过程
# # while True表示能够和一个client说多句话
# conn.recv(1024)
# conn.send(b'xxx')
# conn.close()
# sk.close()  # 四次挥手中的两手

# client -tcp
# import socket
# sk = socket.socket()
# sk.connect(('127.0.0.1',9000))
#
# sk.send(b'hello')
# sk.recv(1024)
# sk.close()   # 四次挥手中的两手

# server -udp
# import socket
# sk = socket.socket(type=socket.SOCK_DGRAM)
# sk.bind(('127.0.0.1',9000))
# while True:
#     msg,cli_addr = sk.recvfrom(1024)
#     sk.sendto(msg,cli_addr)
# sk.close()

# clients -udp
import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.sendto(b'msg',('127.0.0.1',9000))
msg,_ = sk.recvfrom(1024)
print(msg)
sk.close()




并发编程

# by luffycity.com
# 操作系统
# 异步同步阻塞非阻塞并发并行
# 并发和并行
    # 并行 能利用多核 同一时刻 有多个任务在CPU上同时执行
    # 并发 不能利用多核 同一时间段内 有多个任务在一个CPU上轮流被执行
    # 并行 : 多进程 多线程(在其他语言中)
# 同步和异步
    # 同步 当我执行一个任务  需要等待这个任务的结果才能继续执行下一个任务
    # 异步 当我执行某一个任务 不需要等待这个任务的结果 就可以继续执行下一个任务
# 阻塞和非阻塞
    # 非阻塞 : cpu一直在工作
    # 阻塞 : CPU不工作 recv recvfrom accept input sleep
# io操作(输入输出都是针对内存的,str,bytes)
    # input : input read recv recvfrom accept connet close
    # output: write send sendto connet accept close

# 同步阻塞
# def func():
#     import time
#     time.sleep(1)
#
# def func2():
#     func()
#     print(123)
# func2()

# 同步非阻塞
# def func():
#     a = 1
#     b= a+1
#     return b
# def func2():
#     func()
#     print(123)
# func2()

# 异步阻塞
# import time
# import threading
# def func():
#     time.sleep(1)
# t_l = []
# for i in range(10):
#     t = threading.Thread(target=func)
#     t.start()
#     t_l.append(t)
# for t in t_l:t.join()

# 异步非阻塞
# 我调用一个函数 不等待这个函数的结果
# 并且我能一直利用cpu

# 在正常的编程语言中
# 进程 是计算机中最小资源分配单位
    # 数据隔离 开销(开启 销毁 切换)大 内存级别数据安全 但是文件操作数据库操作数据不安全
    # manager : 数据共享
    # IPC(inter process communication):队列消息队列memcache
abbitmq
edis
        # 管道 : 基于socket + pickle
        # 原生的queue : 基于文件(管道 + 锁)
        # 第三方工具 : 基于网络稳定性更强
# 线程 计算机中能被CPU调度的最小单位
    # 数据共享 开销(开启 销毁 切换)小 数据不安全 数据共享程序可能会同时去操作一个变量
# 协程 本质是一条线程 协程任务对于操作系统来说不可见 协程是用户级的单位
    # 数据共享 开销非常小(函数的调用的速度一样快) 数据绝对安全
# 在Cpython解释器下
    # 进程
    # 线程 不能利用多核 (flask django) : 文件操作更快
        # GIL锁 : 全局解释器锁,锁的是线程,保证了同一个进程中的多个线程之间只有一个线程能访问CPU
                 # 限制了一个python进程中的多线程不能利用多核
        # 无法处理高计算型的任务
            # 解决方案 开多进程
    # 协程(tonado tiwsted sanic scrapy) : 所有的time.sleep socket 协程更快
        # 一条线程
        # 指的是程序能够在多个协程任务之间来回切换
        # 如果在程序中遇到io就切换去执行另一个程序,实现了使用协程来规避io,提高cpu的使用率
# def func():
#     yield 1
#     print(123)
#     yield 2
# def func2():
#     g = func()
#     g.__next__()
        # asyncio 基于yield关键字gevent 基于greenlet来完成的
        # aiohttp

# 操作系统中的IO多路复用
# select poll epoll
# select windows
# poll epoll linux
# epoll最好

# 代理,监听所有的网络对象,是否有读写事件发生
# import socket
# import select
# sk = socket.socket()
# sk.setblocking(False)
# sk.bind(('127.0.0.1',9000))
# sk.listen()
# read_l = [sk]
# while True:
#     rl,wl,el = select.select(read_l,[],[])   # 阻塞
#     for item in rl:
#         if item is sk:
#             conn,addr = sk.accept()
#             read_l.append(conn)
#         else:
#             msg = item.recv(1024)
#             if msg == b'':
#                 read_l.remove(item)
#                 continue
#             print(msg)
#             item.send(b'received')
# io多路复用
    # 代理所有的网络对象,帮助我们监听有哪一个对象发生了注册事件(读写异常),然后通知程序,去进行相应的处理

# selectors模块
# 能够有效的利用poll和epoll前提是你所在的操作系统是有这两个机制的
# 自动的识别当前操作系统中我们能用的最好的机制
#服务端
from socket import *
import selectors

sel=selectors.DefaultSelector()
def accept(sk,mask):
    conn,addr=sk.accept()
    sel.register(conn,selectors.EVENT_READ,read)

def read(conn,mask):
    try:
        data=conn.recv(1024)
        if not data:
            print('closing',conn)
            sel.unregister(conn)
            conn.close()
            return
        conn.send(data.upper()+b'_SB')
    except Exception:
        print('closing', conn)
        sel.unregister(conn)
        conn.close()

sk=socket(AF_INET,SOCK_STREAM)
sk.bind(('127.0.0.1',8088))
sk.listen(5)
sk.setblocking(False)

sel.register(sk,selectors.EVENT_READ,accept) #相当于网select的读列表里append了一个文件句柄server_fileobj,并且绑定了一个回调函数accept

while True:
    events=sel.select() # 代理在这里等待,等events事件来,一旦等来了 那么一定是有新的链接 来 或者是有发送给conn的数据来
    for sel_obj,mask in events:
        callback=sel_obj.data #callback=accpet/read
        callback(sel_obj.fileobj,mask) #accpet(server_fileobj,1)

# select 只能使用select
# selector 能用select poll epoll
# select 采用轮询,能够处理的对象的个数有限
# poll 采用轮询,能够处理的对象的个数无限的
# epoll 回调

# TCP协议
# 监听多个sk,conn对象,谁的数据先来,我就通知谁来处理
# 好处是什么
    # 把很个等待变成一个等待,有一个代理替我们来接收所有的请求


# 1.刷一下考试题
    # 把所有课上没有讲过答案的 圈出来


数据库1

# by luffycity.com
# 非关系型数据库
# mongdb 智能玩具
# redis  路飞项目
# kafka 消息中间件

# 关系型数据库
# oracle
# sqllite

# mysql
# ddl dml dcl
# 版本的数据库 5.6/ 5.7 / 8.0
# 存储引擎
    # innodb 5.6版本以上默认的存储引擎
        # 支持事务
            # select + update
            # begin;
            # select * from 表 where 条件 for update;
            # update 表 set 字段=值 where 条件;
            # commit;
        # 行级锁 :
            # 对于少量数据的并发的修改效率更高
            # 但是对于整个表中大量字段的修改锁反而拖慢了速度
        # 支持外键
        #     create table 表名(
        #     字段名 数据类型(长度) 约束,
        #     uid int,
        #     foreign key uid references user(ui)
        #     on update cascade
        #     )
    # myisam 5.5版本以下默认的存储引擎
        # 查询速度和insert的速度都很快
        # 表级锁 : 对高并发的大量修改没有优势的
        # innodb支持的都不支持
    # memory
        # 断电消失
    # blakhole
        # 多级主从复制 往里写啥啥没
        # binary_log = bin_log
        # sql -> 分析 -> 优化 -> 编译 -> 二进制的操作



数据库2

# by luffycity.com
# 数据类型
    # 数字
        # in
        # float
    # 字符串
        # char(4)    定长:存取快 浪费空间 提倡
        # varchar(4) 变长:存取慢 节省空间
    # 时间
        # 内置函数 :now year month day
        # datetime
        # timestamp
        # year date time
    # 枚举和集合
        # enum 枚举单选
        # create table t(gender enum('male','female'))
        # set  集合多选去重
        # create table t(hobby set('抽烟','喝酒'))
# 约束条件
    # 非空 not null
    # 默认值 default
    # 唯一  unique
        # 联合唯一 unique(字段1,字段2)   # 姓和名  # ip和端口
        # 唯一+int 自增 auto_increment
    # 主键 primary key (非空+唯一)
        # 联合主键 primary key(字段1,字段2)
    # 外键 foreign key

# 表结构操作
    # 创建表结构   *****
    # 删除表结构
        # drop table 表名;
    # 修改表结构
        # alter table 表名 add 字段 数据类型 约束信息 first
        # alter table 表名 add 字段 数据类型 约束信息 after 某字段
        # alter table 表名 modify 修改数据的数据类型和约束条件
        # alter table 表名 modify 已经存在的字段名 新的类型 新的约束 first
        # alter table 表名 change 已经存在的字段名 新字段名 新的类型 新的约束 first
        # alter table 表名 drop 字段/索引
    # 查看表结构   *****
        # desc 表名;
        # show create table 表名;




数据库3

# by luffycity.com
# 记录操作 dml
    # 增
        # insert into 表 (字段) values (值1,值2,),(值1,值2,),(值1,值2,);
    # 删
        # delete from table where 条件
        # delete from table;删除整个表中的数据 ,自增字段的offset还在
    # 改
        # update 表 set 字段=值,字段2=值2 where 条件
    # 查
        # 单表
            # select id from 表
                    # where 条件
                    # group by 字段  是可以使用别名的
                    # having 过滤条件 只能查select字段中或者group by 或者使用了过滤条件
                    # order by 排序  asc desc
                    # limit m,n 从m+1开始,取n条
            # having
                # select name from 表 having age>20  # 报错
                # select name from 表 group by age having avg(age)>20  # 正确
                # select name from 表 having avg(age)>20  # 正确
                # select name,age from 表 having age>20  # 正确

        # 多表
            # 连表查询
            # 子查询


client

# by luffycity.com
# import socket
#
# sk = socket.socket()
# sk.connect(('127.0.0.1',9000))
# while True:
#     sk.send(b'hello')
#     print(sk.recv(1024))
# sk.close()

#客户端
from socket import *
c=socket(AF_INET,SOCK_STREAM)
c.connect(('127.0.0.1',8088))

while True:
    msg=input('>>: ')
    if not msg:continue
    c.send(msg.encode('utf-8'))
    data=c.recv(1024)
    print(data.decode('utf-8'))