2010-03-21 56 views
7

我有一個循環,基本上把這種每隔幾秒鐘(超時後):從插座打破了選擇

while(true){ 

    if(finished) 
     return; 

    switch(select(FD_SETSIZE, &readfds, 0, 0, &tv)){ 
     case SOCKET_ERROR : report bad stuff etc; return; 
     default : break; 
    } 

    // do stuff with the incoming connection 
} 

所以基本上每隔幾秒鐘的時間(這是由電視指定),它重新激活監聽。

這是在線程B(不是主線程)上運行的。有時,我想立即從線程A(主線程)結束這個接受器循環,但似乎我必須等到時間間隔完成。

有沒有辦法破壞select函數從另一個線程所以線程B可以立即退出?

+0

旁註:你可以削減if語句,只寫(while!)。 – 2010-03-21 10:40:22

+0

雖然這將需要100%的CPU時間。絕對不能接受。 – kamziro 2010-03-21 11:55:54

+0

哎呀,我一定有誤讀 – kamziro 2010-03-22 05:27:27

回答

9

最簡單的方法可能是使用pipe(2)來創建管道並將讀取結尾添加到readfds。當另一個線程想要中斷select()時,只需寫一個字節,然後將其消耗。

+0

它是一個偵聽器套接字(接受連接的套接字)。這會繼續嗎? 我正在考慮調用一些破壞套接字的函數來查看會發生什麼。這會安全嗎? – kamziro 2010-03-21 12:14:13

+1

它正在等待* a *文件。它不關心*哪個*,它只是想*某件事*。 – 2010-03-21 12:23:46

+0

它工作,我用unix管道瞭解了一兩件事!謝謝!順便說一句,我在中斷後所做的一切都是退出程序。所以我不打擾消費。沒關係吧? – kamziro 2010-03-21 15:06:25

3

是的,你創建一對連接的套接字。然後,線程B寫入套接字的一側,線程A添加另一側的套接字進行選擇。所以一旦B寫入套接字A退出選擇,不要忘記從套接字讀取這個字節。

這是中斷選擇的最普通和最常見的方式。

注:

在Unix下,使用socketpair打造一雙插座,窗下是有點棘手,但谷歌搜索的Windows socketpair會給你的代碼示例。

+0

啊,我剛剛使用了pipe(2),它似乎工作正常。我可能不得不擔心它的窗口對應最終.. – kamziro 2010-03-21 15:07:18

-1

難道你不能讓超時時間足夠短嗎(如10ms左右?)。

這些「只是創建一個虛擬連接」類型的解決方案似乎有點被黑客入侵。我個人認爲,如果一個應用程序設計得很好,併發任務永遠不需要被強行中斷,那麼Just就有足夠的工人檢查(這也是boost.threads沒有終止函數的原因)。

編輯回答了這個問題答。這很糟糕,但它可以幫助其他人理解爲什麼它不好,這在​​評論中解釋過。

+1

-1這是非常糟糕的解決方案,只是成本CPU,仍然有延遲問題。有這樣的標準解決方案。 – Artyom 2010-03-21 10:44:50

+0

這是如何消耗CPU的?與創建虛擬套接字連接相比,等待CPU的時間是多少? – 2010-03-21 10:46:33

+1

CPU成本正在減少超時,使循環運行更頻繁。 – caf 2010-03-21 11:17:00

-1

您可以使用來自主線程的shutdown(Sock,SHUT_RDWR)調用從等待選擇調用中退出,該選擇調用在超時之前也會退出另一個線程,所以不需要等到超時過期。

歡呼聲。 :)

+1

不幸的是,你不能'關閉'監聽套接字。當另一個線程正在或可能正在使用它時,沒有安全的方法來「關閉」它。 – 2016-04-08 07:39:30

+0

如果您有下面提到的套接字線程函數,並且您從主線程發送關機(sock,SHUT_RD),它將喚醒等待來自在其他線程中執行的SockThreadFunction的選擇調用。我已經試過這個,它的工作正常。 SockThreadFunction(){while(SocketOpen) {//等待選擇呼叫 int Ready = select(pSocket-> m_Sock + 1,&SockSet,0,0,0); } – 2016-05-04 08:51:40

+0

他有一個監聽套接字。你不能關閉一個監聽套接字。它將適用於連接的套接字,但它不適用於監聽套接字,這是他所擁有的。 – 2016-05-04 09:06:01