2013-10-21 51 views
2

下面的策略似乎運作良好:使用多線程與接受()在非阻塞監聽器在每個過程

什麼不好運行是EPOLLIN在回調中用accept()看每個線程/進程的監聽套接字。這會喚醒每個線程/進程,儘管只有一個人可以成功接受()ing。這就像阻塞accept()的糟糕的舊時代,當連接會進入時導致踩踏事件。

有沒有辦法讓一個線程/進程在仍然使用EPOLLIN的情況下喚醒accept()?或者我應該重寫使用阻塞accept(),只是使用線程隔離?

這不是隻有一個線程/進程運行accept()的選項,因爲我試圖以一種方式管理進程作爲池,每個進程不需要知道它是否是唯一的守護進程接受()在偵聽器套接字上。

回答

2

您需要使用EPOLLETEPOLLONESHOT,這樣只有一個線程被通過時,一個新的連接進來的EPOLLIN事件喚醒,然後將處理線程需要調用accept在一個循環,直到它返回EAGAINEPOLLET)或手動復位與epoll_ctlEPOLLONESHOT)爲了更多的連接被處理。

一般情況下,當使用多線程和epoll時,要使用EPOLLETEPOLLONESHOT。否則,當一個事件發生時,多個線程將被喚醒來處理它們,並且它們可能會相互干擾。最好的情況是,他們只會浪費時間來計算出其他線程在再次等待之前正在處理事件。最糟糕的是,他們會陷入僵局或腐敗的東西。

+0

使用'EPOLLONESHOT',我仍然可以從'accept()'看到'EAGAIN'。這是預期的嗎?我沒有看到我只用'EPOLLIN'做的踩踏事件,但是我是否仍然期望某些進程無法接受()?? –

1

多個套接字在相同的proto +地址+端口上偵聽呢?這可以通過Linux SO_REUSERPORT完成。 https://lwn.net/Articles/542629/。我還沒有嘗試過,但我認爲即使使用epoll也應該可以工作,因爲只有一個套接字獲取實際事件。

告誡emptor這是一個非可移植的Linux僅解決方案。 SO_REUSEPORT也存在鏈接文章中詳述的一些錯誤/功能。

+0

這不是一個關於如何將多個線程或進程綁定到同一端口或讓他們訪問同一個偵聽器套接字的問題。一旦已經完成,就是如何在accept()之間進行協調。 –

+1

@DavidTimothyStrauss正如我所瞭解的,SO_REUSEPORT在進程之間平均分配連接,所以不需要您進行協調。 – thuovila