最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2020年06月22日 08:53:56   作者:wztshine  
這篇文章主要介紹了Python select及selectors模塊概念用法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

 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 select
import socket
import sys
import 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 socket
import sys

sock = 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 selectors
import socket

# 根據(jù)平臺(tái)自動(dòng)選擇最佳的IO多路機(jī)制,比如linux就會(huì)選擇epoll,windows會(huì)選擇select
sel = 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 socket
tin=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í)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • FFrpc python客戶端lib使用解析

    FFrpc python客戶端lib使用解析

    這篇文章主要介紹了FFrpc python客戶端lib使用解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • python實(shí)現(xiàn)對(duì)一個(gè)完整url進(jìn)行分割的方法

    python實(shí)現(xiàn)對(duì)一個(gè)完整url進(jìn)行分割的方法

    這篇文章主要介紹了python實(shí)現(xiàn)對(duì)一個(gè)完整url進(jìn)行分割的方法,涉及Python操作URL的相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-04-04
  • Python打印酷炫日志的方法詳解

    Python打印酷炫日志的方法詳解

    在Python中,日志是一種非常重要的工具,可以幫助我們更好地了解程序的運(yùn)行情況,本文將介紹如何使用logging模塊來(lái)打印炫酷的日志,需要的可以參考一下
    2023-06-06
  • Pycharm pyuic5實(shí)現(xiàn)將ui文件轉(zhuǎn)為py文件,讓UI界面成功顯示

    Pycharm pyuic5實(shí)現(xiàn)將ui文件轉(zhuǎn)為py文件,讓UI界面成功顯示

    這篇文章主要介紹了Pycharm pyuic5實(shí)現(xiàn)將ui文件轉(zhuǎn)為py文件,讓UI界面成功顯示,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-04-04
  • python+selenium+Chrome options參數(shù)的使用

    python+selenium+Chrome options參數(shù)的使用

    這篇文章主要介紹了python+selenium+Chrome options參數(shù)的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • python多線程掃描端口示例

    python多線程掃描端口示例

    這篇文章主要介紹了python多線程掃描端口示例,大家參考使用吧
    2014-01-01
  • Django自定義排序ORM示例詳解

    Django自定義排序ORM示例詳解

    這篇文章主要為大家介紹了Django自定義排序ORM示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • python heic后綴圖片文件轉(zhuǎn)換成jpg格式的操作

    python heic后綴圖片文件轉(zhuǎn)換成jpg格式的操作

    這篇文章主要介紹了python heic后綴圖片文件轉(zhuǎn)換成jpg格式的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-03-03
  • 基于Python制作一個(gè)惡搞代碼

    基于Python制作一個(gè)惡搞代碼

    這篇文章主要為大家詳細(xì)介紹了如何基于Python和Tkinter制作一個(gè)惡搞代碼--無(wú)限彈窗,每天寫(xiě)一些有趣的小程序,帶你成為一個(gè)浪漫的程序員
    2023-08-08
  • Python3.0 實(shí)現(xiàn)決策樹(shù)算法的流程

    Python3.0 實(shí)現(xiàn)決策樹(shù)算法的流程

    這篇文章主要介紹了Python3.0 實(shí)現(xiàn)決策樹(shù)算法的流程,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-08-08

最新評(píng)論

汽车| 开远市| 宜宾市| 长岛县| 墨玉县| 邵阳市| 宁晋县| 德阳市| 共和县| 桐城市| 岑巩县| 临夏县| 龙井市| 连城县| 西乌珠穆沁旗| 沁水县| 突泉县| 西盟| 和龙市| 崇明县| 新平| 新津县| 大余县| 嵊泗县| 阿拉尔市| 临泉县| 多伦县| 山西省| 西昌市| 黑龙江省| 万载县| 房山区| 怀化市| 侯马市| 惠来县| 天门市| 烟台市| 湾仔区| 奉新县| 临夏县| 盖州市|