亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Python select及selectors模塊概念用法詳解

瀏覽:19日期:2022-07-20 09:00:43

1. select模塊

針對(duì)select,要先理解其他幾個(gè)概念:

文件描述符:

文件描述符在形式上是一個(gè)非負(fù)整數(shù)。實(shí)際上,它是一個(gè)索引值,指向內(nèi)核為每一個(gè)進(jìn)程所維護(hù)的該進(jìn)程打開(kāi)文件的記錄表。當(dāng)程序打開(kāi)一個(gè)現(xiàn)有文件或者創(chuàng)建一個(gè)新文件時(shí),內(nèi)核向進(jìn)程返回一個(gè)文件描述符。

內(nèi)核空間:

Linux簡(jiǎn)化了分段機(jī)制,使得虛擬地址與線性地址總是一致,因此,Linux的虛擬地址空間也為0~4G。Linux內(nèi)核將這4G字節(jié)的空間分為兩部分。將最高的1G字節(jié)(從虛擬地址0xC0000000到0xFFFFFFFF),供內(nèi)核使用,稱為“內(nèi)核空間”。而將較低的3G字節(jié)(從虛擬地址 0x00000000到0xBFFFFFFF),供各個(gè)進(jìn)程使用,稱為“用戶空間)。因?yàn)槊總€(gè)進(jìn)程可以通過(guò)系統(tǒng)調(diào)用進(jìn)入內(nèi)核,因此,Linux內(nèi)核由系統(tǒng)內(nèi)的所有進(jìn)程共享。于是,從具體進(jìn)程的角度來(lái)看,每個(gè)進(jìn)程可以擁有4G字節(jié)的虛擬空間。

內(nèi)核空間中存放的是內(nèi)核代碼和數(shù)據(jù),而進(jìn)程的用戶空間中存放的是用戶程序的代碼和數(shù)據(jù)。不管是內(nèi)核空間還是用戶空間,它們都處于虛擬空間中。

內(nèi)核空間和用戶空間一般通過(guò)系統(tǒng)調(diào)用進(jìn)行通信。

select就是針對(duì)許多文件描述符(簡(jiǎn)稱fd)進(jìn)行監(jiān)控,它有三個(gè)參數(shù):

rlist -- wait until ready for reading wlist -- wait until ready for writing xlist -- wait for an 'exceptional condition'

第一個(gè)參數(shù)監(jiān)控 進(jìn)來(lái)的 數(shù)據(jù)的fd列表,select監(jiān)控這個(gè)列表,等待這些fd發(fā)送過(guò)來(lái)數(shù)據(jù),一旦數(shù)據(jù)發(fā)送過(guò)來(lái)了(可以讀取了),就返回一個(gè)可讀的fd列表

第二個(gè)參數(shù)監(jiān)控 出去的 數(shù)據(jù)的fd列表,select監(jiān)控這個(gè)列表,等待這些fd發(fā)送出去數(shù)據(jù),一旦fd準(zhǔn)備好發(fā)送了(可以寫(xiě)入了),就返回一個(gè)可寫(xiě)的fd列表

第三個(gè)參數(shù)監(jiān)控fd列表,返回出異常的fd列表

服務(wù)端:

import selectimport socketimport sysimport queue# 生成socket對(duì)象server = socket.socket()# 設(shè)置非阻塞模式server.setblocking(False)# 綁定地址,設(shè)置監(jiān)聽(tīng)server.bind((’localhost’,9999))server.listen(5)# 將自己也放進(jìn)待監(jiān)測(cè)列表里inputs = [server, ]outputs = []message_queues = {}while True: ’’’ 關(guān)于socket可讀可寫(xiě)的判斷,可以參考博客:https://blog.csdn.net/majianfei1023/article/details/45788591 ’’’ rlist, wlist, elist = select.select(inputs,outputs,inputs) #如果沒(méi)有任何fd就緒,那程序就會(huì)一直阻塞在這里 for r in rlist: # 遍歷已經(jīng)可以準(zhǔn)備讀取數(shù)據(jù)的 fd if r is server: # 如果這個(gè) fd 是server,即 server 有數(shù)據(jù)待接收讀取,說(shuō)明有新的客戶端連接過(guò)來(lái)了 conn, client_addr = r.accept() print('new connection from',client_addr) conn.setblocking(False) inputs.append(conn) # 將這個(gè)新的客戶端連接添加到檢測(cè)的列表中 message_queues[conn] = queue.Queue() # 用隊(duì)列存儲(chǔ)客戶端發(fā)送來(lái)的數(shù)據(jù),等待服務(wù)器統(tǒng)一返回?cái)?shù)據(jù) else: # 這個(gè)可讀的 r 不是服務(wù)器,那就是某個(gè)客戶端。就是說(shuō)客戶端發(fā)送數(shù)據(jù)過(guò)來(lái)了,這些數(shù)據(jù)處于待讀取狀態(tài) try: # 異常處理,這是為了防止客戶端異常斷開(kāi)報(bào)錯(cuò)(比如手動(dòng)關(guān)掉客戶端黑窗口,服務(wù)器也會(huì)跟著報(bào)錯(cuò)退出)data = r.recv(1024)if data: # 根據(jù)判斷data是否為空,判斷客戶端是否斷開(kāi) print('收到來(lái)自[%s]的數(shù)據(jù):' % r.getpeername()[0], data) message_queues[r].put(data) # 收到的數(shù)據(jù)先放到queue里,一會(huì)返回給客戶端 if r not in outputs: outputs.append(r) # 放進(jìn)可寫(xiě)的fd列表中,表明這些 fd 已經(jīng)準(zhǔn)備好去發(fā)送數(shù)據(jù)了。else: # 如果數(shù)據(jù)為空,表明客戶端斷開(kāi)了 print(’客戶端斷開(kāi)了’) if r in outputs: outputs.remove(r) # 清理已斷開(kāi)的連接 inputs.remove(r) # 清理已斷開(kāi)的連接 del message_queues[r] # 清理已斷開(kāi)的連接 except ConnectionResetError: # 如果報(bào)錯(cuò),說(shuō)明客戶端斷開(kāi)了print('客戶端異常斷開(kāi)了', r)if r in outputs: outputs.remove(r) # 清理已斷開(kāi)的連接inputs.remove(r) # 清理已斷開(kāi)的連接del message_queues[r] # 清理已斷開(kāi)的連接 for w in wlist: # 遍歷可寫(xiě)的 fd 列表,即準(zhǔn)備好發(fā)送數(shù)據(jù)的那些fd # 判斷隊(duì)列是否為空 try : next_msg = message_queues[w].get_nowait() except queue.Empty: # print('client [%s]' % w.getpeername()[0], 'queue is empty..') outputs.remove(w) # 隊(duì)列不為空,就把隊(duì)列中的數(shù)據(jù)改成大寫(xiě),原樣發(fā)回去 else: # print('sending msg to [%s]'% w.getpeername()[0], next_msg) w.send(next_msg.upper()) for e in elist: # 處理報(bào)錯(cuò)的 fd e.close() print('Error occured in ',e.getpeername()) inputs.remove(e) if e in outputs: outputs.remove(e) del message_queues[e]

客戶端:

import socketimport syssock = socket.socket()sock.connect((’localhost’,9999))while True: c = input(’>>>:’).strip() sock.send(c.encode()) data = sock.recv(1024) print(data.decode())sock.close()

2. selectors模塊

官方文檔:https://docs.python.org/3/library/selectors.html

服務(wù)端:

import selectorsimport socket# 根據(jù)平臺(tái)自動(dòng)選擇最佳的IO多路機(jī)制,比如linux就會(huì)選擇epoll,windows會(huì)選擇selectsel = selectors.DefaultSelector()def accept(sock, mask): # 建立客戶端連接 conn, addr = sock.accept() print(’accepted’, conn, ’from’, addr) # 設(shè)置非阻塞模式 conn.setblocking(False) # 再次注冊(cè)一個(gè)連接,將其加入監(jiān)測(cè)列表中, sel.register(conn, selectors.EVENT_READ, read)def read(conn, mask): try: # 拋出客戶端強(qiáng)制關(guān)閉的異常(如手動(dòng)關(guān)閉客戶端黑窗口) data = conn.recv(1000) # Should be ready if data: print(’echoing’, repr(data), ’to’, conn) conn.send(data) # Hope it won’t block else: print(’Client closed.’, conn) # 將conn從監(jiān)測(cè)列表刪除 sel.unregister(conn) conn.close() except ConnectionResetError: print(’Client forcibly closed.’, conn) # 將conn從監(jiān)測(cè)列表刪除 sel.unregister(conn) conn.close()# 創(chuàng)建socket對(duì)象sock = socket.socket()# 綁定端口,設(shè)置監(jiān)聽(tīng)sock.bind((’localhost’, 1234))sock.listen(100)# 設(shè)置為非阻塞模式sock.setblocking(False)# 注冊(cè)一個(gè)文件對(duì)象,監(jiān)測(cè)它的IO事件,data是和文件對(duì)象相關(guān)的數(shù)據(jù)(此處放置了一個(gè) accept 函數(shù)的內(nèi)存地址)# register(fileobj, events, data=None)sel.register(sock, selectors.EVENT_READ, accept)while True: ’’’ sel.select() 看似是select方法,實(shí)際上會(huì)根據(jù)平臺(tái)自動(dòng)選擇使用select還是epoll 它返回一個(gè)(key, events)元組, key是一個(gè)namedtuple類型的元組,可以使用 key.name 獲取元組的數(shù)據(jù) key 的內(nèi)容(fileobj,fd,events,data): fileobj 已經(jīng)注冊(cè)的文件對(duì)象 fd 也就是第一個(gè)參數(shù)的那個(gè)文件對(duì)象的更底層的文件描述符 events 等待的IO事件 data 可選項(xiàng)。可以存一些和fileobj有關(guān)的數(shù)據(jù),如 sessioin 的 id ’’’ events = sel.select() # 監(jiān)測(cè)有無(wú)活動(dòng)對(duì)象,沒(méi)有就阻塞在這里等待 for key, mask in events: # 有活動(dòng)對(duì)象了 callback = key.data # key.data 是注冊(cè)時(shí)傳遞的 accept 函數(shù) callback(key.fileobj, mask) # key.fileobj 就是傳遞的 socket 對(duì)象

客戶端:

import sockettin=socket.socket()tin.connect((’localhost’,1234))while True: inp=input(’>>>>’) tin.send(inp.encode(’utf8’)) data=tin.recv(1024) print(data.decode(’utf8’))

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 日本一区二区三区久久 | 亚洲欧美色图 | 国产日本三级在线播放线观看 | 在线观看日本永久免费视频 | 色婷婷在线视频 | 成年人视频网站免费 | a级粗大硬长爽猛视频免费 a级精品国产片在线观看 | 免费a级黄毛片 | 国产成人亚洲精品乱码在线观看 | 亚洲精品欧美综合四区 | 大陆三级特黄在线播放 | 国产精品第44页 | 爱爱免费网站 | 无圣光福利视频 | 国产网站在线免费观看 | 亚洲综合图片网 | 国产精品福利久久香蕉中文 | 成年美女xx网站高清视频 | 国产51| 亚洲妇熟xxxxx妇色黄 | 免费一级大毛片a一观看不卡 | 国产女人的一级毛片视频 | 人妖xxxx | 一本大道一卡2卡三卡4卡麻豆 | 天天色资料 | 涩涩网站在线看 | 日本三级黄网站 | 护士xxxx做爰| 日韩欧美精品中文字幕 | 亚洲精品欧美精品一区二区 | xxxxxx国产精品视频 | 特级全黄一级毛片免费 | 国产麻豆自拍 | aaa国产一级毛片 | 一级久久| 美国一级毛片免费 | 亚洲精品国产成人一区二区 | 麻豆精品免费视频入口 | 国产精品久久天天影视 | 欧美黄色性 | 精品国产免费观看 |