python中的epoll

epoll是對(duì)select状勤、poll模型的改進(jìn)致燥,提高了網(wǎng)絡(luò)編程的性能莲祸,廣泛應(yīng)用于大規(guī)模并發(fā)請(qǐng)求的C/S架構(gòu)中酪穿。

原理圖

epoll

一般步驟

  1. Create an epoll object——?jiǎng)?chuàng)建1個(gè)epoll對(duì)象
  2. Tell the epoll object to monitor specific events on specific sockets——告訴epoll對(duì)象,在指定的socket上監(jiān)聽(tīng)指定的事件
  3. Ask the epoll object which sockets may have had the specified event since the last query——詢(xún)問(wèn)epoll對(duì)象辫红,從上次查詢(xún)以來(lái)李请,哪些socket發(fā)生了哪些指定的事件
  4. Perform some action on those sockets——在這些socket上執(zhí)行一些操作
  5. Tell the epoll object to modify the list of sockets and/or events to monitor——告訴epoll對(duì)象,修改socket列表和(或)事件厉熟,并監(jiān)控
  6. Repeat steps 3 through 5 until finished——重復(fù)步驟3-5,直到完成
  7. Destroy the epoll object——銷(xiāo)毀epoll對(duì)象

相關(guān)用法

import select                       //導(dǎo)入select模塊
epoll = select.epoll()           //創(chuàng)建一個(gè)epoll對(duì)象
epoll.register                      //(文件句柄,事件類(lèi)型) 注冊(cè)要監(jiān)控的文件句柄和事件
事件類(lèi)型:
  select.EPOLLIN    可讀事件
  select.EPOLLOUT   可寫(xiě)事件
  select.EPOLLERR   錯(cuò)誤事件
  select.EPOLLHUP   客戶(hù)端斷開(kāi)事件
epoll.unregister                //(文件句柄)   銷(xiāo)毀文件句柄
epoll.poll(timeout)            //當(dāng)文件句柄發(fā)生變化较幌,則會(huì)以列表的形式主動(dòng)報(bào)告給用戶(hù)進(jìn)程,timeout為超時(shí)時(shí)間揍瑟,默認(rèn)為-1,即一直等待直到文件句柄發(fā)生變化乍炉,如果指定為1那么epoll每1秒?yún)R報(bào)一次當(dāng)前文件句柄的變化情況绢片,如果無(wú)變化則返回空
epoll.fileno()                            //返回epoll的控制文件描述符(Return the epoll control file descriptor)
epoll.modfiy(fineno,event)      //fineno為文件描述符 event為事件類(lèi)型  作用是修改文件描述符所對(duì)應(yīng)的事件
epoll.fromfd(fileno)                 //從1個(gè)指定的文件描述符創(chuàng)建1個(gè)epoll對(duì)象
epoll.close()                           //關(guān)閉epoll對(duì)象的控制文件描述符

實(shí)例:客戶(hù)端發(fā)送數(shù)據(jù) 服務(wù)端將接收的數(shù)據(jù)返回給客戶(hù)端

服務(wù)端代碼

1 #!/usr/bin/env python
 2 #-*- coding:utf-8 -*-
 3 
 4 import socket
 5 import select
 6 import Queue
 7 
 8 #創(chuàng)建socket對(duì)象
 9 serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
10 #設(shè)置IP地址復(fù)用
11 serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
12 #ip地址和端口號(hào)
13 server_address = ("127.0.0.1", 8888)
14 #綁定IP地址
15 serversocket.bind(server_address)
16 #監(jiān)聽(tīng),并設(shè)置最大連接數(shù)
17 serversocket.listen(10)
18 print  "服務(wù)器啟動(dòng)成功岛琼,監(jiān)聽(tīng)I(yíng)P:" , server_address
19 #服務(wù)端設(shè)置非阻塞
20 serversocket.setblocking(False)  
21 #超時(shí)時(shí)間
22 timeout = 10
23 #創(chuàng)建epoll事件對(duì)象底循,后續(xù)要監(jiān)控的事件添加到其中
24 epoll = select.epoll()
25 #注冊(cè)服務(wù)器監(jiān)聽(tīng)fd到等待讀事件集合
26 epoll.register(serversocket.fileno(), select.EPOLLIN)
27 #保存連接客戶(hù)端消息的字典,格式為{}
28 message_queues = {}
29 #文件句柄到所對(duì)應(yīng)對(duì)象的字典槐瑞,格式為{句柄:對(duì)象}
30 fd_to_socket = {serversocket.fileno():serversocket,}
31 
32 while True:
33   print "等待活動(dòng)連接......"
34   #輪詢(xún)注冊(cè)的事件集合熙涤,返回值為[(文件句柄,對(duì)應(yīng)的事件),(...),....]
35   events = epoll.poll(timeout)
36   if not events:
37      print "epoll超時(shí)無(wú)活動(dòng)連接祠挫,重新輪詢(xún)......"
38      continue
39   print "有" , len(events), "個(gè)新事件那槽,開(kāi)始處理......"
40   
41   for fd, event in events:
42      socket = fd_to_socket[fd]
43      #如果活動(dòng)socket為當(dāng)前服務(wù)器socket,表示有新連接
44      if socket == serversocket:
45             connection, address = serversocket.accept()
46             print "新連接:" , address
47             #新連接socket設(shè)置為非阻塞
48             connection.setblocking(False)
49             #注冊(cè)新連接fd到待讀事件集合
50             epoll.register(connection.fileno(), select.EPOLLIN)
51             #把新連接的文件句柄以及對(duì)象保存到字典
52             fd_to_socket[connection.fileno()] = connection
53             #以新連接的對(duì)象為鍵值等舔,值存儲(chǔ)在隊(duì)列中骚灸,保存每個(gè)連接的信息
54             message_queues[connection]  = Queue.Queue()
55      #關(guān)閉事件
56      elif event & select.EPOLLHUP:
57         print 'client close'
58         #在epoll中注銷(xiāo)客戶(hù)端的文件句柄
59         epoll.unregister(fd)
60         #關(guān)閉客戶(hù)端的文件句柄
61         fd_to_socket[fd].close()
62         #在字典中刪除與已關(guān)閉客戶(hù)端相關(guān)的信息
63         del fd_to_socket[fd]
64      #可讀事件
65      elif event & select.EPOLLIN:
66         #接收數(shù)據(jù)
67         data = socket.recv(1024)
68         if data:
69            print "收到數(shù)據(jù):" , data , "客戶(hù)端:" , socket.getpeername()
70            #將數(shù)據(jù)放入對(duì)應(yīng)客戶(hù)端的字典
71            message_queues[socket].put(data)
72            #修改讀取到消息的連接到等待寫(xiě)事件集合(即對(duì)應(yīng)客戶(hù)端收到消息后,再將其fd修改并加入寫(xiě)事件集合)
73            epoll.modify(fd, select.EPOLLOUT)
74      #可寫(xiě)事件
75      elif event & select.EPOLLOUT:
76         try:
77            #從字典中獲取對(duì)應(yīng)客戶(hù)端的信息
78            msg = message_queues[socket].get_nowait()
79         except Queue.Empty:
80            print socket.getpeername() , " queue empty"
81            #修改文件句柄為讀事件
82            epoll.modify(fd, select.EPOLLIN)
83         else :
84            print "發(fā)送數(shù)據(jù):" , data , "客戶(hù)端:" , socket.getpeername()
85            #發(fā)送數(shù)據(jù)
86            socket.send(msg)
87 
88 #在epoll中注銷(xiāo)服務(wù)端文件句柄
89 epoll.unregister(serversocket.fileno())
90 #關(guān)閉epoll
91 epoll.close()
92 #關(guān)閉服務(wù)器socket
93 serversocket.close()

客戶(hù)端代碼

1 #!/usr/bin/env python
 2 #-*- coding:utf-8 -*-
 3 
 4 import socket
 5 
 6 #創(chuàng)建客戶(hù)端socket對(duì)象
 7 clientsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 8 #服務(wù)端IP地址和端口號(hào)元組
 9 server_address = ('127.0.0.1',8888)
10 #客戶(hù)端連接指定的IP地址和端口號(hào)
11 clientsocket.connect(server_address)
12 
13 while True:
14     #輸入數(shù)據(jù)
15     data = raw_input('please input:')
16     #客戶(hù)端發(fā)送數(shù)據(jù)
17     clientsocket.sendall(data)
18     #客戶(hù)端接收數(shù)據(jù)
19     server_data = clientsocket.recv(1024)
20     print '客戶(hù)端收到的數(shù)據(jù):'server_data
21     #關(guān)閉客戶(hù)端socket
22     clientsocket.close() 
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末慌植,一起剝皮案震驚了整個(gè)濱河市甚牲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蝶柿,老刑警劉巖丈钙,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異只锭,居然都是意外死亡著恩,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)蜻展,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)喉誊,“玉大人,你說(shuō)我怎么就攤上這事纵顾∥榍眩” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵施逾,是天一觀(guān)的道長(zhǎng)敷矫。 經(jīng)常有香客問(wèn)我,道長(zhǎng)汉额,這世上最難降的妖魔是什么曹仗? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮蠕搜,結(jié)果婚禮上怎茫,老公的妹妹穿的比我還像新娘。我一直安慰自己妓灌,他們只是感情好轨蛤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著虫埂,像睡著了一般祥山。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上掉伏,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天缝呕,我揣著相機(jī)與錄音澳窑,去河邊找鬼。 笑死岳颇,一個(gè)胖子當(dāng)著我的面吹牛照捡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播话侧,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼栗精,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了瞻鹏?” 一聲冷哼從身側(cè)響起悲立,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎新博,沒(méi)想到半個(gè)月后薪夕,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赫悄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年原献,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片埂淮。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡姑隅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出倔撞,到底是詐尸還是另有隱情讲仰,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布痪蝇,位于F島的核電站鄙陡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏躏啰。R本人自食惡果不足惜趁矾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望给僵。 院中可真熱鬧愈魏,春花似錦、人聲如沸想际。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)胡本。三九已至,卻和暖如春畸悬,著一層夾襖步出監(jiān)牢的瞬間侧甫,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留披粟,地道東北人咒锻。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像守屉,于是被迫代替她去往敵國(guó)和親惑艇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容