IO多路復用之select

2021-10-25 00:18:36 字數 2103 閱讀 8778

原理: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...