1. 程式人生 > >單程序伺服器-epoll版-TCP伺服器

單程序伺服器-epoll版-TCP伺服器

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時,不會再次響應應用程式並通知此事