原理:i/o多路復用就通過一種機制,可以監視多個描述符,一旦某個描述符就緒,能夠通知程式進行相應的操作。
select執行流程
select需要提供要監控的陣列,然後由使用者態拷貝到核心態
核心態線性迴圈監控陣列,每次都需要遍歷整個陣列
核心發現檔案描述符狀態符合操作結果,將其返回
所以對於我們監控的socket都要設定為非阻塞的,只有這樣才能保證不會被阻塞
優點
基本各個平台都支援
缺點
每次呼叫select,都需要把fd集合由使用者態拷貝到核心態,在fd多的時候開銷會很大
單個程序能夠監控的fd數量存在最大限制,因為其使用的資料結構是陣列
。
每次select都是線性遍歷整個陣列,當fd很大的時候,遍歷的開銷也很大
所以對於我們監控的socket都要設定為非阻塞的,只有這樣才能保證不會被阻塞
服務端
import select
import socket
socket_server = socket.socket(socket.af_inet, socket.sock_stream)
socket_server.getsockopt(socket.sol_socket, socket.so_reuseaddr,1)
socket_server.bind((''
,10002))
socket_server.listen(5)
# 接收連線佇列
rlist =
[socket_server]
# 應答佇列
wlist =
# 錯處理的io事件
xlist =
while
true
:# 監控io發生
rs, ws, xs = select.select(rlist, wlist, xlist)
# 遍歷三個返回值列表,判斷哪個io發生
for r in rs:
# 如果是套接字準備就緒,處理連線
if r == socket_server:
c, addr = r.accept(
)print
("connect from: "
, addr)
print
("當前連線套接字的檔案描述符:"
, c.fileno())
# 將客戶端套接字加入新的關注io
# 用於溝通的新客戶端套接字
else
: data = r.recv(
1024)if
not data:
# 客戶端斷開連線,將客戶端套接字關閉,並且從監控列表中移除
rlist.remove(r)
r.close(
)continue
print
(data.decode(
"utf-8"))
# 主動處理這個io,作應答
for w in ws:
w.send(b'ok'
) wlist.remove(w)
for x in xs:
pass
客戶端
import socket
flag =
1s = socket.socket(
)s.connect(
('127.0.0.1'
,10002))
while flag:
input_msg =
input
('input>>>'
)if input_msg ==
'0':
break
s.sendall(input_msg.encode())
msg = s.recv(
1024
)print
(msg.decode())
s.close(
)
I O多路復用之select
阻塞i o模型 應用程式呼叫乙個i o函式,應用程式會一直等待資料準備好。如果資料沒有準備好,就會一直等待。只有當資料準備好,從核心拷貝到使用者空間io函式才成功返回。非阻塞i o模型 把乙個套介面設定成非阻塞告訴核心,當所有的i o操作無法完成時,不要將程序睡眠,而返回乙個錯誤資訊。此時i o操作...
IO多路復用之select
1 背景知識 我們首先來看看伺服器程式設計的模型,客戶端發來的請求服務端會產生乙個程序來對其進行服務,每當來乙個客戶請求就產生乙個程序來服務,然而程序不可能無限制的產生,因此為了解決大量客戶端訪問的問題,引入了io復用技術。即 乙個程序可以同時對多個客戶請求進行服務。也就是說io復用的 介質 是程序...
I O多路復用之select
select是用於監視多個檔案描述符狀態的變化的。即用來監視檔案描述符讀 寫 異常狀態是否就緒。函式原型 int select int nfds,fd set readfds,fd set writefds,fd set exceptfds,struct timeval timeout select...