摘要:的應用很多乃至攜程都跟它又關系所以趁著失業的無聊的事件從基礎學起了解下的用法在的包含了訪問庫的。
#
epoll的應用很多,nginx,tornado,乃至攜程,都跟它又關系.所以趁著失業的無聊的事件,從基礎學起,了解下epoll的用法
epoll 在python的apiPython包含了訪問Linux epoll庫的API。這篇文章用幾個簡單的例子來展示下這個API
常用apiselect.epoll() #返回創建epoll對象 epoll.register(fd[, eventmask]) #將fd的事件注冊到epoll對象中 epoll.unregister(fd) #去除fd epoll.poll([timeout=-1[, maxevents=-1]]) #等待事件 epoll.modify(fd, eventmask) #更改fd關注的事件
更多api文檔,可以在dash中查看
常用事件常量EPOLLIN 可讀事件 EPOLLOUT 可寫事件 EPOLLERR 錯誤事件 EPOLLHUP 掛起事件示例代碼
以下是簡單的helloword 程序,運行程序后,瀏覽器訪問localhost:8080/ 輸出helloword
# coding: utf-8 import socket, select from ipdb import set_trace EOL1 = b" " EOL2 = b" " response = b"HTTP/1.0 200 OK Date: Mon, 1 Jan 1996 01:01:01 GMT " response += b"Content-Type: text/plain Content-Length: 13 " response += b"Hello, world!" serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) serversocket.bind(("0.0.0.0", 8080)) serversocket.listen(10240) serversocket.setblocking(0) serversocket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) #創建epoll對象,epoll對象是個存儲"fd-事件"的容器,把關注的"fd-事件"注冊到容器中, #接下來就可以監聽到fd的事件 epoll = select.epoll() #將server的sockect注冊到epoll中,因為此示例程序功能是瀏覽器顯示helloword, #所以關注接入的客戶端fd,當有客戶端連接時,出發的一定是server sockect的EPOLLIN epoll.register(serversocket.fileno(), select.EPOLLIN) try: connections = {}; requests = {}; responses = {} while True: events = epoll.poll(10) # print "=="*10 for fileno, event in events: #客戶端接入時,注冊客戶端fd到epoll,第一步需要讀取客戶端發送到服務端的信息,所以用EPOLLIN if fileno == serversocket.fileno(): connection, address = serversocket.accept() connection.setblocking(0) epoll.register(connection.fileno(), select.EPOLLIN) connections[connection.fileno()] = connection requests[connection.fileno()] = b"" responses[connection.fileno()] = response #讀取客戶端信息 elif event & select.EPOLLIN: data=connections[fileno].recv(1024) requests[fileno] += data #判斷客戶端信息是否讀取完畢 if EOL1 in requests[fileno] or EOL2 in requests[fileno]: epoll.modify(fileno, select.EPOLLOUT) print("-"*40 + str(fileno) + " " + requests[fileno].decode()[:-2]) #處理客戶端關閉請求時的信息,防止服務端程序出現close_wait #使用telnet測試后發現,客戶端主動關閉時會發送個空信息到客戶端,不處理的話,會出現close_wait, #并且循環中每次都會出現該事件,會嚴重影響程序處理效率,因此需要把它從epoll重移除 if data == b"": print "receiv client close : %s "% str(fileno) epoll.unregister(fileno) try : connections[fileno].close() except Exception, e: print " connection was allready closed....."+e #將此接入返回給客戶端 elif event & select.EPOLLOUT: byteswritten = connections[fileno].send(responses[fileno]) responses[fileno] = responses[fileno][byteswritten:] if len(responses[fileno]) == 0: epoll.modify(fileno, 0) try: connections[fileno].shutdown(socket.SHUT_RDWR) except Exception, e: print " connection was allready closed....." + e #服務端主動關閉連接時的邏輯處理 elif event & select.EPOLLHUP: print "close fd : %s "% str(fileno) epoll.unregister(fileno) connections[fileno].close() del connections[fileno] else : print "="*10 print fileno,event finally: # set_trace() epoll.unregister(serversocket.fileno()) epoll.close() serversocket.close()總結
這段程序大部分摘抄自http://scotdoyle.com/python-epoll-howto.html
但經過測試發現他的程序有些bug.
使用telnet測試后發現,客戶端主動關閉時會發送個空信息到客戶端,不處理的話,會出現close_wait.
并且循環中每次都會出現該事件,會嚴重影響程序處理效率,因此需要把它從epoll重移除.
原因發生tcp協議中四次握手時,客戶端的關閉消息沒有被處理
理解這些bug對epoll使用很有幫助
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/37558.html
摘要:在之前的版本中,一直不支持協程化,在代碼中無法使用。由于使用了庫實現,無法直接它的,版本使用模擬實現了的,并在底層替換了等函數的。跟蹤使用跟蹤發現,所有系統調用均變成的異步非阻塞調用了。 在4.4之前的版本中,Swoole一直不支持CURL協程化,在代碼中無法使用curl。由于curl使用了libcurl庫實現,無法直接hook它的socket,4.4版本使用SwooleCorouti...
閱讀 1120·2021-11-25 09:43
閱讀 1569·2021-10-25 09:47
閱讀 2466·2019-08-30 13:46
閱讀 753·2019-08-29 13:45
閱讀 1280·2019-08-26 13:29
閱讀 2990·2019-08-23 15:30
閱讀 1103·2019-08-23 14:17
閱讀 1326·2019-08-23 13:43