單程序伺服器-epoll版-TCP伺服器
阿新 • • 發佈:2018-12-02
1. epoll的優點:
1). 沒有最大併發連線的限制,能開啟的FD(指的是檔案描述符,通俗的理解就是套接字對應的數字編號)的上限遠小於1024
2). 效率提升,不是輪詢的方式,不會隨著FD數目的增加效率下降。只有活躍可用的FD才會呼叫callback函式;即epoll最大的優點就在於它只管你“活躍”的連線,而跟連線總數無關,因此在實際的網路環境中,epoll的效率就會遠遠高於select和poll。
2. epoll使用參考程式碼
import socket import select # 建立套接字 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 設定可以重複使用繫結的資訊 s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # 繫結本機資訊 s.bind(("",7788)) # 變為被動 s.listen(10) # 建立一個epoll物件 epoll=select.epoll() # 測試,用來列印套接字對應的檔案描述符 # print s.fileno() # print select.EPOLLIN|select.EPOLLET # 註冊事件到epoll中 # epoll.register(fd[, eventmask]) # 注意,如果fd已經註冊過,則會發生異常 # 將建立的套接字新增到epoll的事件監聽中 epoll.register(s.fileno(),select.EPOLLIN|select.EPOLLET) connections = {} addresses = {} # 迴圈等待客戶端的到來或者對方傳送資料 while True: # epoll 進行 fd 掃描的地方 -- 未指定超時時間則為阻塞等待 epoll_list=epoll.poll() # 對事件進行判斷 for fd,events in epoll_list: # print fd # print events # 如果是socket建立的套接字被啟用 if fd == s.fileno(): conn,addr=s.accept() print('有新的客戶端到來%s'%str(addr)) # 將 conn 和 addr 資訊分別儲存起來 connections[conn.fileno()] = conn addresses[conn.fileno()] = addr # 向epoll中註冊連線socket的可讀事件 epoll.register(conn.fileno(), select.EPOLLIN | select.EPOLLE) elif events == select.EPOLLIN: # 從啟用fd上接收 recvData = connections[fd].recv(1024) if len(recvData)>0: print('recv:%s'%recvData) else: # 從epol中移除該連線fd epoll.unregister(fd) # server側主動關閉該連線fd connections[fd].close() print("%s---offline---"%str(addresses[fd]))
2. 說明
1)EPOLLIN (可讀)
2)EPOLLOUT (可寫)
3)EPOLLET (ET模式)
epoll對檔案描述符的操作有兩種模式:LT(level trigger)和ET(edgetrigger)。LT模式是預設模式,LT模式與ET模式的區別如下:
LT模式:當epoll檢測到描述符事件發生並將此事件通知應用程式,應用程式可以不立即處理該事件。下次呼叫epoll時,會再次響應應用程式並通知此事 ET模式:當epoll檢測到描述符事件發生並將此事件通知應用程式,應用程式必須立即處理該事件。如果不處理,下次呼叫epoll時,不會再次響應應用程式並通知此事