**原理圖**

1. Create an epoll object——創建1個epoll對象
2. Tell the epoll object to monitor specific events on specific sockets——告訴epoll對象,在指定的socket上監聽指定的事件
3. Ask the epoll object which sockets may have had the specified event since the last query——詢問epoll對象,從上次查詢以來,哪些socket發生了哪些指定的事件
4. Perform some action on those sockets——在這些socket上執行一些操作
5. Tell the epoll object to modify the list of sockets and/or events to monitor——告訴epoll對象,修改socket列表和(或)事件,并監控
6. Repeat steps 3 through 5 until finished——重復步驟3-5,直到完成
7. Destroy the epoll object——銷毀epoll對象
**相關用法**
~~~
import select 導入select模塊
epoll = select.epoll() 創建一個epoll對象
epoll.register(文件句柄,事件類型) 注冊要監控的文件句柄和事件
事件類型:
select.EPOLLIN 可讀事件
select.EPOLLOUT 可寫事件
select.EPOLLERR 錯誤事件
select.EPOLLHUP 客戶端斷開事件
epoll.unregister(文件句柄) 銷毀文件句柄
epoll.poll(timeout) 當文件句柄發生變化,則會以列表的形式主動報告給用戶進程,timeout
為超時時間,默認為-1,即一直等待直到文件句柄發生變化,如果指定為1
那么epoll每1秒匯報一次當前文件句柄的變化情況,如果無變化則返回空
epoll.fileno() 返回epoll的控制文件描述符(Return the epoll control file descriptor)
epoll.modfiy(fineno,event) fineno為文件描述符 event為事件類型 作用是修改文件描述符所對應的事件
epoll.fromfd(fileno) 從1個指定的文件描述符創建1個epoll對象
epoll.close() 關閉epoll對象的控制文件描述符
~~~
注:EPOLLIN(可讀),EPOLLOUT(可寫)
* EPOLLET: 邊緣觸發模式(只通知一次)
* EPOLLLT:水平觸發模式(通知后沒有做處理的話還會繼續通知)
~~~
import socket
import select
tcp_server_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_tcp.bind(('0.0.0.0', 9292))
tcp_server_tcp.listen(128)
# 設置套接字為非阻塞方式
tcp_server_tcp.setblocking(False)
# 創建一個epoll對象
epl = select.epoll()
# 將監聽套接字對應的fd注冊到epoll中
epl.register(tcp_server_tcp.fileno(), select.EPOLLIN)
# fd為key,socket為value
fd_event_dict = dict()
while True:
# 默認阻塞,直到os監測到數據到來,通過事件通知的方式,此時才會解開阻塞
# epl.poll(10) 里面可以寫超時時間
fd_event_list = epl.poll() # 結果是這樣,[(fd, event), (套接字對應的文件描述符,這個文件描述符到底是什么事件,例如,可以調用recv接收等)]
if not fd_event_list:
print("epoll超時無活動連接,重新輪詢......")
continue
print("有", len(fd_event_list), "個新事件,開始處理......")
for fd, event in fd_event_list:
# 如果活動socket為當前服務器socket,表示有新連接
if fd == tcp_server_tcp.fileno():
# 等待新客戶端的鏈接
new_socket, client_addr = tcp_server_tcp.accept()
# 注冊新連接fd到待讀事件集合
epl.register(new_socket.fileno(), select.EPOLLIN)
# 把新連接的文件句柄以及對象保存到字典
fd_event_dict[new_socket.fileno()] = new_socket
elif event == select.EPOLLIN:
# 判斷已經鏈接的客戶端是否有數據發送過來
recv__data = fd_event_dict[fd].recv(1024).decode('utf-8', 'ignore')
if recv__data:
print('收到的數據是: ', recv__data)
# 發送數據回去
fd_event_dict[fd].send(recv__data.encode('utf-8'))
else:
fd_event_dict[fd].close()
epl.unregister(fd)
del fd_event_dict [fd]
~~~
- python入門
- 軟件安裝
- anaconda使用
- py解釋器
- 數據類型和變量
- 編碼
- 字符串
- 格式化
- 數據類型
- 運算符
- list和tuple
- 列表生成式
- dict和set
- 切片和迭代
- set,list,tuple之間互換
- is和==
- 公共方法
- 反射操作
- 數學運算
- 類型轉換
- 對象操作
- 序列操作
- 運算符
- 內置函數
- 交互操作
- 編譯執行
- 引用
- 判斷,循環
- 生成器
- 迭代器
- 函數
- 數據類型轉換
- 空函數
- 參數
- 全局變量
- 返回值
- 遞歸
- 匿名函數
- 文件操作
- 打開和關閉
- 讀寫
- 備份文件
- 文件定位讀寫
- 重命名,刪除
- 文件夾相關操作
- with
- StringIO和BytesIO
- 操作文件和目錄
- 序列化
- 文件屬性
- 面向對象
- 類和對象
- init()方法
- 魔法方法
- 繼承
- 重寫
- 多態
- 類屬性,實例屬性
- 靜態方法和類方法
- 工廠模式
- 單例模式
- 異常
- 私有化
- 獲取對象信息
- *args和**kwargs
- property屬性
- 元類
- slots
- 定制類
- 枚舉
- 模塊
- 模塊介紹
- 模塊中的__name__
- 模塊中的__all__
- 包
- 模塊發布
- 模塊的安裝和使用
- 多模塊開發
- 標準庫
- 給程序傳參數
- 時間
- 正則表達式
- GIL
- 深拷貝和淺拷貝
- 單元測試
- pyqt
- 安裝
- 設置窗口圖標和移動窗口
- 設置氣泡提示和文本
- 圖片展示
- 文本框控件
- 按鈕控件
- 信號和槽
- 布局
- 對話框控件
- pygame
- 窗體關閉事件
- 顯示圖片
- 移動圖片
- 文本顯示
- 背景音和音效
- FPS計算
- surface
- 鼠標事件
- 函數式編程
- map/reduce
- filter
- sorted
- 返回函數
- 裝飾器
- 偏函數
- 網絡編程
- tcp
- udp
- socket
- epoll
- WSGI
- 多任務
- 多線程
- 多進程
- 分布式進程
- 協程
- 迭代器
- 生成器
- yield多任務
- greenlet
- gevent
- ThreadLocal
- asyncio
- async/await
- aiohttp
- 常用內建模塊
- datetime
- collections
- base64
- struct
- hashlib
- hmac
- itertools
- urllib
- xml
- HTMLParser
- 常用第三方模塊
- pillow
- requests
- chardet
- psutil
- 圖形界面
- 海龜繪圖
- Django
- 虛擬環境搭建
- ORM
- 模型類設計和表生成
- 模型類操作
- 關系查詢
- 后臺管理
- 配置mysql
- 字段屬性和選項
- 查詢
- 模型關聯
- 路由
- 模板
- selenium
- 基本原理
- api
- 八種定位方式
- 元素的操作
- 多標簽
- 多表單
- 鼠標,鍵盤
- 警告框
- 下拉框
- 執行js
- 等待
- cookie
- 封裝
- unittest模塊
- 斷言
- 測試用例
- jmeter
- jmeter簡介
- jmeter提取json
- 添加header和cookie
- 讀取csv/txt文件
- 配置文件
- ant