Python select模組簡單理解與使用

2021-10-01 06:55:38 字數 4767 閱讀 3737

select()的機制中提供一fd_set的資料結構,實際上是一long型別的陣列, 每乙個陣列元素都能與一開啟的檔案控制代碼(不管是socket控制代碼,還是其他檔案或命名管道或裝置控制代碼)建立聯絡,建立聯絡的工作由程式設計師完成, 當呼叫select()時,由核心根據io狀態修改fd_set的內容,由此來通知執行了select()的程序哪一socket或檔案可讀或可寫。主要用於socket通訊當中。

select方法

程序指定核心監聽哪些檔案描述符(最多監聽1024個fd)的哪些事件,當沒有檔案描述符事件發生時,程序被阻塞;當乙個或者多個檔案描述符事件發生時,程序被喚醒。

當我們呼叫select()時:

1 上下文切換轉換為核心態

2 將fd從使用者空間複製到核心空間

3 核心遍歷所有fd,檢視其對應事件是否發生

4 如果沒發生,將程序阻塞,當裝置驅動產生中斷或者timeout時間後,將程序喚醒,再次進行遍歷

5 返回遍歷後的fd

6 將fd從核心空間複製到使用者空間

fd:file descriptor 檔案描述符

總結:select主要用於socket通訊當中,能監視我們需要的檔案描述變化。

-----------------------------分割線------------------------------

fd_r_list, fd_w_list, fd_e_list = select.select(rlist, wlist, xlist, [timeout])

引數: 可接受四個引數(前三個必須)

rlist: wait until ready for reading

wlist: wait until ready for writing

xlist: wait for an 「exceptional condition」

timeout: 超時時間

返回值:三個列表

select方法用來監視檔案描述符(當檔案描述符條件不滿足時,select會阻塞),當某個檔案描述符狀態改變後,會返回三個列表

1、當引數1 序列中的fd滿足「可讀」條件時,則獲取發生變化的fd並新增到fd_r_list中

2、當引數2 序列中含有fd時,則將該序列中所有的fd新增到 fd_w_list中

3、當引數3 序列中的fd發生錯誤時,則將該發生錯誤的fd新增到 fd_e_list中

4、當超時時間為空,則select會一直阻塞,直到監聽的控制代碼發生變化

當超時時間 = n(正整數)時,那麼如果監聽的控制代碼均無任何變化,則select會阻塞n秒,之後返回三個空列表,如果監聽的控制代碼有變化,則直接執行。

-----------------------------分割線-----------------------------------

非阻塞式i/o程式設計特點:服務端:

import socket

import select

sk1 = socket.socket(

)sk1.bind(

('0.0.0.0'

,8001))

sk1.listen(

)sk2 = socket.socket(

)sk2.bind(

('0.0.0.0'

,8002))

sk2.listen(

)sk3 = socket.socket(

)sk3.bind(

('0.0.0.0'

,8003))

sk3.listen(

)inputs =

[sk1, sk2, sk3,

]while

true

: r_list, w_list, e_list = select.select(inputs,

,inputs,1)

for sk in r_list:

# conn表示每乙個連線物件

conn, address = sk.accept(

) conn.sendall(

bytes

('hello'

, encoding=

'utf-8'))

conn.close(

)for sk in e_list:

inputs.remove(sk)

**解釋

1.select內部自動監聽sk1,sk2,sk3三個物件,監聽三個控制代碼是否發生變化,把發生變化的元素放入r_list中。

2.如果有人連線sk1,則r_list = [sk1]

3.如果有人連線sk1和sk2,則r_list = [sk1,sk2]

4.select中第1個引數表示inputs中發生變化的控制代碼放入r_list。

5.select中第2個引數表示中的值原封不動的傳遞給w_list。

6.select中第3個引數表示inputs中發生錯誤的控制代碼放入e_list。

7.引數1表示1秒監聽一次

8.當有使用者連線時,r_list裡面的內容

客戶端:

import socket

obj = socket.socket(

)obj.connect(

('127.0.0.1'

,8001))

content =

str(obj.recv(

1024

), encoding=

'utf-8'

)print

(content)

obj.close(

)# 客戶端c2.py

import socket

obj = socket.socket(

)obj.connect(

('127.0.0.1'

,8002))

content =

str(obj.recv(

1024

), encoding=

'utf-8'

)print

(content)

obj.close(

)

服務端
#使用socket模擬多執行緒,使多使用者可以同時連線

import socket

import select

sk1 = socket.socket(

)sk1.bind(

('0.0.0.0'

,8001))

sk1.listen(

)inputs =

[sk1,

]outputs =

message_dict =

while

true

: r_list, w_list, e_list = select.select(inputs, outputs, inputs,1)

print

('正在監聽的socket物件%d'

%len

(inputs)

)print

(r_list)

for sk1_or_conn in r_list:

#每乙個連線物件

if sk1_or_conn == sk1:

# 表示有新使用者來連線

conn, address = sk1_or_conn.accept(

) message_dict[conn]=[

]else

:# 有老使用者發訊息了

try:

data_bytes = sk1_or_conn.recv(

1024

)except exception as ex:

# 如果使用者終止連線

inputs.remove(sk1_or_conn)

else

: data_str =

str(data_bytes, encoding=

'utf-8'

) message_dict[sk1_or_conn]

#w_list中僅僅儲存了誰給我發過訊息

for conn in w_list:

recv_str = message_dict[conn][0

]del message_dict[conn][0

] conn.sendall(

bytes

(recv_str+

'好', encoding=

'utf-8'))

outputs.remove(conn)

for sk in e_list:

inputs.remove(sk)

客戶端:
import socket

obj = socket.socket(

)obj.connect(

('127.0.0.1'

,8001))

while

true

: inp =

input

('>>>'

) obj.sendall(

bytes

(inp, encoding=

'utf-8'))

ret =

str(obj.recv(

1024

),encoding=

'utf-8'

)print

(ret)

obj.close(

)

python select實現非阻塞socket

python select實現非阻塞socket liukeforever的專欄 部落格頻道 csdn.net 分類 python 2011 10 19 11 08 690人閱讀收藏 舉報 python view plain copy print usr bin env python encodin...

python select實現非阻塞socket

python select實現非阻塞socket 郭猛的個人空間 開源中國社群 python select實現非阻塞socket usr bin env python encoding utf 8 import socket import select host port 50000 s socke...

json模組簡析

使用json模組處理json資料首先要先導入。import json1,它是處理字典與json字串之間的轉換問題,字典是一種資料結構,他有很多方法可供呼叫,而json只是一種特定格式的資料,json字串是符合json格式的字串。字典裡key和value的值的型別可以是任何型別,一般使用單引號,但不強...