第二部分
網絡編程之 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'))