#!/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....