第二部分
网络编程之 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\rabbitmq\redis
# 管道 : 基于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'))