IO input output
在內存中存在數據交換的操作可以任務是IO操作(輸入輸出)
e.g.
內存和磁盤進行數據交換:文件的讀寫,數據庫更新
內存和終端數據交換:input ; print ; sys.stdin;sys.stdout;sys.stderr
內存和網絡數據的交換:網絡鏈接 recv;send;recvfrom
IO密集型程序:程序中執行中由大量的IO操作,而較少的cpu運算操作;消耗cpu較少,IO運行時間長
CPU(計算)密集型程序:程序中存在大量的cpu運算,IO操作較少,消耗cpu大
IO分類
- 阻塞IO:
程序運行中遇到IO條件沒有達成或者傳輸過程較慢的情況會出現阻塞狀態;IO最簡單的邏輯情形,也是默認狀態。---->效率低的IO形態
阻塞情況:
×因爲某種IO條件沒有達到形成阻塞:e.g.、accept、recv、recvfrom、input
×處理IO事件的時候耗時較長形成阻塞:e.g.、文件讀寫過程,網絡數據發送過程
- 非阻塞IO:在程序運行中遇到IO的情形不讓其產生阻塞
×實現手段:改變IO事件的屬性,讓其變爲非阻塞
×通常會和循環一起使用,進行條件的循環監控
s.setblocking(False)
功能:將套接字設置爲非堵塞
參數:默認爲堵塞狀態,設置爲False則爲非阻塞
超時檢測:將原本阻塞的函數,設置一個阻塞的最長時間,在時間內如果仍然阻塞則不再等待
s.settimeout(sec)
功能:設置套接字的超時時間
參數:時間(秒)
- IO多路複用:
×定義:通過一個監測,可以同時監控多個IO事件的行爲,當那個IO事件可以執行,即讓這個IO事件發生
×IO事件就緒:IO事件即將發生的一個臨界狀態
1.在程序中存在的IO事件中選擇要檢測的
2.創建檢測,將檢測的IO時間註冊
3.等待檢測的IO事件發生,判斷是什麼IO事件
4.處理響應的IO
import select
select -->windows\linux\unix
poll -->linux\unix
epoll -->linux\unix
rs,ws,xs = select(rlist,wlist,xlist[,timeout])
功能:監控IO事件,阻塞等待監控的IO時間發生
參數:
- rlist 列表:存放我們需要等待處理的IO
- wlist 列表:存放我們想主動處理的IO
- xlist 列表:存放出錯希望去處理的IO
- timeout 超時檢測
返回值: - rs:rlist中準備就緒的IO
- ws:wlist中準備就緒的IO
- xs:xlist中準備就緒的IO
from socket import *
from select import select
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(("192.168.0.106",8888))
s.listen(1024)
rlist = [s]
wlist = []
xlist = [s]
while True:
print("等待IO發生")
rs,ws,xs = select(rlist,wlist,xlist)
for r in rs:
if r is s:
connfd,addr = rs[0].accept()
print("Connet from ",addr)
rlist.append(connfd)
#表示客戶端連接套接字準備就緒
else:
data = r.recv(1024)
if not data:
#從關注列表移除
rlist.remove(r)
r.close()
else:
print("Recevie:",data.decode())
#將套接字放入wlist
wlist.append(r)
#ie your message!")
for w in ws:
w.send("這是一條回覆消息".encode())
wlist.remove(w)
for x in xs:
if x is s:
s.close()
#poll
from socket import *
from select import *
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(("192.168.0.106",8888))
s.listen(1024)
#創建poll對象
p = poll()
#創建地圖
fdmap = {s.fileno():s}
#添加關注
p.register(s,POLLIN|POLLERR)
while True:
#進行IO監控
#[(fileno,event),(),...]
events = p.poll()
for fd,event in events:
if fd == s.fileno():
#從地圖中找到fd對應的對象
c,addr = fdmap[fd].accept()
#註冊新的IO維護地圖
p.register(c,POLLIN)
fdmap[c.fileno()] = c
else:
data = fdmap[fd].recv(1024)
if not data:
p.unregister(fd) #從
fdmap[fd].close()
del fdmap[fd] #從地圖刪除
else:
print(data.decode())
fdmap[fd].send('收到了'.encode())
#epoll
from socket import *
from select import *
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(("192.168.0.106",8888))
s.listen(1024)
#創建epoll對象
p = epoll()
#創建地圖
fdmap = {s.fileno():s}
#添加關注
p.register(s,EPOLLIN|EPOLLERR)
while True:
#進行IO監控
#[(fileno,event),(),...]
events = p.poll()
for fd,event in events:
if fd == s.fileno():
#從地圖中找到fd對應的對象
c,addr = fdmap[fd].accept()
#註冊新的IO維護地圖
p.register(c,EPOLLIN)
fdmap[c.fileno()] = c
else:
data = fdmap[fd].recv(1024)
if not data:
p.unregister(fd) #從
fdmap[fd].close()
del fdmap[fd] #從地圖刪除
else:
print(data.decode())
fdmap[fd].send('收到了'.encode())
區別:
epoll 效率要高於select和poll
epoll 的觸發機制要多—>EPOLLET(邊緣觸發)
- 事件驅動IO
- 異步IO
本地套接字
cookie
linux下文件類型
b(塊設備文件) c(字符設備文件)
d(目錄) -(普通文件) l(鏈接文件)
s(套接字文件) p(管道文件)
作用:用於本地不同程序之間進行數據傳輸
本地套接字創建流程
1.創建套接字對象
sockfd = socket(AF_UNIX,SOCK_STREAM)
2.綁定套接字文件,如果文件不存在則自動創建
sockfd.bind(file)
3.監聽
listen
4.消息收發
recv、send
os.path.exists(file)
功能:判斷一個文件是否存在
參數:文件
返回值:存在True 不存在 False
os.remove()
os.unlink()
功能:刪除一個文件
參數:要刪除的文件
網絡基礎總結
理論
- 1.OSI七層模型, tcp/ip模型
- 2.tcp 和UDP的區別特徵
- 3.三次握手和四次揮手的過程
- 4.什麼是IO多路複用,IO的基本形態
- 5.套接字的種類,套接字的類型區別
程序實踐:
1.TCP套接字傳輸的基本模型
2.UDP套接字傳輸的基本類型
3.IO多路複用select、poll的使用
4.http協議基本原理的實現