1. 程式人生 > >epoll中監聽套接字的觸發模式

epoll中監聽套接字的觸發模式

我們知道epoll有兩種觸發模式:水平觸發(LT)和邊緣觸發(ET)

LT模式

  1. 若資料可讀,epoll返回可讀事件 若開發者沒有把資料完全讀完,epoll會不斷通知資料可讀,直到資料全部被讀取。
  2. 若socket可寫,epoll返回可寫事件,而且是隻要socket傳送緩衝區未滿,就一直通知可寫事件。
  3. 優點是對於read操作比較簡單,只要有read事件就讀,讀多讀少都可以。

ET模式

  1. 若socket可讀,返回可讀事件。
  2. 若沒有把所有資料讀取完畢,epoll不會再次通知epoll read事件,也就是說存在一種隱患,如果在讀到可讀事件時,沒有讀取全部資料,那麼可能導致epoll再也不會通知該socket的read事件。
  3. ET模式下,只有socket的狀態發生變化時才會通知,也就是讀取緩衝區由無資料到有資料時通知read事件,傳送緩衝區由滿變成未滿通知write事件。

簡單說明一下兩種觸發模式的特點後,來說一下我遇到的問題:我自己寫了一個http伺服器,使用了epoll加執行緒池的reactor模式,並且只支援HTTP短連線,所以當瀏覽器請求一個較複雜的web頁面時,伺服器會接收到較多的併發連線,這些是前提。今天在伺服器程式碼基本完成後,進行了測試。
在測試中我發現:在瀏覽器發出較多請求或者頻繁重新整理頁面時,總會有幾個請求得不到響應。所以就抓包來分析了一下,抓包結果可以看到未響應的請求事實上已經和伺服器完成了三次握手,而我在伺服器中打log卻並沒有看到伺服器與該請求建立了連線。所以分析可能是accept函式沒有成功,經測試發現實際上accept並沒有被呼叫。
這裡要說明一下,accept實際上與TCP的三次握手並沒有關聯,它只是從監聽套接字的監聽佇列中取出一個套接字,當然了,前提是監聽佇列非空。這就可以聯想到,抓包發現瀏覽器已經與伺服器完成了三次握手並建立了連線,也就是說現在的監聽佇列非空,然而accept卻沒有被呼叫,這顯然產生了矛盾。
問題出在哪裡呢?我想到可能是epoll中的監聽套接字沒有觸發EPOLLIN事件,想到我對於監聽套接字設定了ET模式,那麼可能會發生下面的情況:有多個連線同時到達監聽埠,這時監聽佇列由空變為非空,EPOLLIN事件被觸發,但是我在程式中只進行了一次accept,所以只有一個連線被接受,之後儘管監聽佇列非空,由於在ET模式下,也不會再次觸發EPOLL事件了。
想到這裡,我趕緊去把程式碼中監聽套接字的觸發模式改為LT模式,果然bug被消除了。所以可以得到結論:在epoll中,監聽套接字的觸發模式最好設定為LT模式

當然了也可以使用ET,不過要使用while迴圈呼叫accept,直到監聽佇列為空。

相關推薦

epoll觸發模式

我們知道epoll有兩種觸發模式:水平觸發(LT)和邊緣觸發(ET) LT模式 若資料可讀,epoll返回可讀事件 若開發者沒有把資料完全讀完,epoll會不斷通知資料可讀,直到資料全部被讀取。 若socket可寫,epoll返回可寫事件,而且

accept和已連線

int accept(int sockfd, struct sockaddr* cliaddr, socklen_t *addrlen); 該函式用於從已完成連線的佇列隊頭返回下一個已完成連線。 其中sockfd為監聽套接字 cliaddr和addrlen由核心填入

在io複用設為非阻塞

  往往在select 或 epoll 中把 listen_socket 設定為非阻塞 O_NONBLOCK 原因是出在 accept 上, 比如有這麼一個客戶端 : RST客戶端 當這個select或epoll 的伺服器非常繁忙時, 有這麼一個一連線就斷開的客戶端,

linux epoll例項

linux epoll機制用於IO多路複用,能夠同時監聽多個接字,使用起來比較簡單。相關介面: #include <sys/epoll.h> int epoll_create(int size); int epoll_cr

[實驗]關閉TCP對已建立連線的影響

先說結果吧,結果是無影響,已建立的連線依然可以正常使用。 實驗環境 windows10,vs2010 實驗過程 伺服器採用VC程式設計,客戶端使用TCP除錯軟體。 伺服器工作流程 1、建立監聽套接字socket1,繫結埠17000。 2、使用listen函式監聽

連線的區別

摘要:對於伺服器程式設計中最重要的一步等待並接受客戶的連線,那麼這一步在程式設計中如何完成,accept函式就是完成這一步的。它從核心中取出已經建立的客戶連線,然後把這個已經建立的連線返回給使用者程式,此時使用者程式就可以與自己的客戶進行點到點的通訊了。 accept函式等

TCP如何區分和已連線???

2.10 TCP埠號與併發伺服器 併發伺服器中主伺服器迴圈通過派生一個子程序來處理每個新的連線。如果一個子程序繼續使用伺服器眾所周知的埠來服務一個長時間的請求,那將發生什麼?讓我們來看一個典型的序列。首先,在主機freebsd上啟動伺服器,該主機是多宿的,其IP地址為12.106.32.254和192.1

連線

摘要:對於伺服器程式設計中最重要的一步等待並接受客戶的連線,那麼這一步在程式設計中如何完成,accept函式就是完成這一步的。它從核心中取出已經建立的客戶連線,然後把這個已經建立的連線返回給使用者程式,此時使用者程式就可以與自己的客戶進行點到點的通訊了。 accept函式

Qt使用 windows 程式設計 客戶端demo

在Qt裡面使用connect需要加上兩個::不然會與訊號連線衝突 WSADATA wsa; if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {     cout << "WSAStartup faile

poll,epoll方法,本地,多工程式設計,父子程序

poll from select  import  poll 1. 建立poll物件 p = poll() 2. 新增關注的IO poll  IO 事件分類 POLLIN  POLLOUT  POLLERR  POLLH

JMeter的HTTPS錯誤

https class true 調試 tls boolean 工作 間接 prop Apache JMeter對啟用SSL的應用程序執行性能和/或負載測試時,SSL套接字錯誤可能是經常遇到的麻煩,嚴重阻礙了您的測試工作。本文重點介紹如何通過相應地配置和調優JMeter來克

初學Node.js使用TCP程式設計

一:建立TCP伺服器var net =require('net');var HOST ='127.0.0.1';var PORT =6969;// 建立一個TCP伺服器例項,呼叫listen函式開始監聽指定埠// 傳入net.createServer()的回撥函式將作為”c

用原始實現網路

 作者:張志強 下載原始碼 1、引言    網路監聽工具(sinff)是提供給網路管理員的一類管理工具。在乙太網中(Ethernet),當網路上連線多臺計算機時,某瞬間只能有一臺計算機可以傳送資料。乙太網中,資料是以被稱為幀的資料結構為單位進行交換的。通常,在計算機網路上交換

Java的理解

java中套接字的理解 什麽是socket,以及兩端ServerSocket和Socket是真正的幹什麽用的,也終於理解到其實普通的socket也就僅僅是普通管道,兩邊通過這個管道互相傳和接受信息。建立Socket連接建立Socket連接至少需要一對套接字,其中一個運行於客戶端,稱為ClientSocket,

Linux下詳解---epoll模式下的IO多路複用伺服器

1 epoll模型簡介 epoll可是當前在Linux下開發大規模併發網路程式的熱門人選,epoll 在Linux2.6核心中正式引入,和select相似,其實都I/O多路複用技術而已,並沒有什麼神祕的。 其實在Linux下設計併發網路程式,向來不缺少方法,比如典型的Apache模型(Proce

網路程式設計time_wait的作用和選項SO_REUSEADDR

這兩天看APUE為一個簡單的問題特別惱火,該問題起源於兩個套接字選項就是SO_REUSEADDR和SO_REUSEPORT其實在看的過程中問學長了,學長解釋的也比較清楚,就是自己悟性不好,一時半會沒理解。自己在網上找了幾篇優秀的部落格看了,受益頗多! 先從套接字選項SO_REUSEADD

淺析SO_REUSEPORT和SO_REUSEADDR的區別

Socket的基本背景 在討論這兩個選項的區別時,我們需要知道的是BSD實現是所有socket實現的起源。基本上其他所有的系統某種程度上都參考了BSD socket實現(或者至少是其介面),然後開始了它們自己的獨立發展進化。顯然,BSD本身也是隨著時間在不斷髮

vue之在頁面鍵盤的Enter鍵來觸發某個按鈕事件

專案中得需求:給頁面某個按鈕繫結Enter鍵,但是按鈕不在form中,直接給按鈕繫結後此按鈕只有獲取了焦點按鍵才會觸發,顯然,一直保持按鈕獲取焦點是不現實得。所以通過查詢等,結合專案需求,完成了下面得程式碼,希望對大家有用,歡迎一起探討,Email:[email p

Linux下詳解(十)---epoll模式下的IO多路複用伺服器

1 epoll模型簡介 epoll可是當前在Linux下開發大規模併發網路程式的熱門人選,epoll 在Linux2.6核心中正式引入,和select相似,其實都I/O多路複用技術而已,並沒有什麼神祕的。 其實在Linux下設計併發網路程式,向來不缺少

非阻塞epoll

要求: 1、從配置檔案中讀取資料; 2、編寫可滾動的日誌檔案; 3、實現非阻塞套接字,應用epoll; 4、實現心跳檢測(心跳包); 5、分執行緒處理 client.c    客戶機程式 #include "head.h" #include "config.h" #inc