python之epoll伺服器原始碼分析

2021-09-07 11:23:24 字數 3499 閱讀 9942

#!/usr/bin/env python

# -*- coding: utf8 -*-import socket,

select

eol1 = b'

/r/n

'eol2 = b'

/r/n/r/n

'# 拼接成的response

'# 建立乙個服務端的socket,來監聽是否有請求過來

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(

1) # 監聽

serversocket.setblocking(

0) # 設定時非阻塞

print(serversocket.fileno())

epoll = select

.epoll() # 準備設計乙個io多路復用

epoll.register(serversocket.fileno(),

select

.epollin) # 把上面的serversocket的fileno() 和 監聽準備讀訊號 註冊到epoll中去

try:

# 設定三個空字典

connections ={}

requests ={}

responses ={}

while

true:

# 檢視epoll是否有訊號有的話,就放在events中

events = epoll.poll(1

) # 迴圈events,分別拿到 檔案描述號 和對應的事件

for fileno, event

inevents:

# 如果當前的檔案描述號是serversocket,那麼說明有新的連線

if fileno ==serversocket.fileno():

# 所以就得接受,建立了 連線,拿到了對方的ip位址

connection, address =serversocket.accept()

# connection就是客戶端連線過來建立的socket,設定為非阻塞

connection.setblocking(0)

# 客戶端建立的socket也註冊到select模組的io多路復用中去

epoll.register(connection.fileno(),

select

.epollin)

# 以connection的檔案描述號 作為鍵 socket作為值儲存在connections中

connections[connection.fileno()] =connection

# 同時在requests和responses字典中,

# requests中 以connection.fileno() 作為鍵 以請求的內容作為值

# responses中 以connection.fileno() 作為鍵 以相應的內容作為值,這個我們返回的是固定的,僅僅返回hello world

requests[connection.fileno()] = b''

responses[connection.fileno()] =response

# 如果請求的資料不是socketserver,那肯定是客戶端的,判斷是否是準備讀的訊號

elif

event & select

.epollin:

# 立馬來開始讀取資料,加到requests物件套接字的內容中去

requests[fileno] += connections[fileno].recv(1024

) # 判斷換行 和 兩個換行是否在接收過來的資料中

if eol1 in requests[fileno] or eol2 in

requests[fileno]:

# 如果是的話,就將這個套接字的監聽更新為準備寫

epoll.modify(fileno,

select

.epollout)

# 列印40個-,然後換行,加上請求的內容

print('-

' * 40 + '

/n' + requests[fileno].decode()[:-2

]) # 如果請求的資料不是socketserver,那肯定是客戶端的,判斷是否是準備寫的訊號

elif

event & select

.epollout:

# 立馬來開始讀取資料,就將response的對應的套接字型大小對應的值拿出來,其實就是hello world,o(∩_∩)o哈哈~# 並統計傳送了多少個位元組

byteswritten =connections[fileno].send(responses[fileno])

# 更新response對應套接字內容為剩下的內容

responses[fileno] =responses[fileno][byteswritten:]

# 如果內容發完了,剩下的長度就是0,如果長度是0

if len(responses[fileno]) == 0

: # 就修改select,不監聽該套接字的內容,其就變成了epollhup

epoll.modify(fileno, 0)

# 然後關閉該socket的管道

connections[fileno].shutdown(socket.shut_rdwr)

elif

event & select

.epollhup:

# 如果不監聽該套接字的內容,就將其登出掉

epoll.unregister(fileno)

# 關閉該套接字

connections[fileno].close()

# 從連線中刪除該檔案描述符

del connections[fileno]

finally

: # 最後關閉serversocket伺服器套接字

epoll.unregister(serversocket.fileno())

# 關閉epoll

epoll.close()

# 套接字關閉

serversocket.close()

高效能伺服器之epoll

什麼是epoll epoll是什麼?是為處理 大批量控制代碼 而作了改進的poll。它 幾乎具備了之前所說的 一切優點,被公認為linux2.6下效能最好的多路i o就緒通 知 方法。epoll的相關系統調 用 epoll只有epoll create,epoll ctl,epoll wait 3個系...

epoll回聲伺服器

epoll是在linux系統中,一種高效率的i o復用技術.在linux的網路程式設計中,很長的時間都在使用select來做事件觸發。在linux新的核心中,有了一種替換它的機制,就是epoll。相比於select,epoll最大的好處在於它不會隨著監聽fd數目的增長而降低效率。因為在核心中的sel...

Web伺服器 併發伺服器 Epoll(3 4 5)

epoll是一種解決方案,nginx就是用的這個 中心思想 不要再使用多程序,多執行緒了,使用單程序,單執行緒去實現併發 在上面部落格實現的 中使用過的輪詢去檢視套接字有沒有資料,而epoll是主動通知 當使用多程序的時候,是複製乙份資源去檢視,epoll不用複製,直接來 優勢 1.共享記憶體 2....