2014-09-30 22 views
1

我將同時寫入來自TCP/IP連接和共享內存隊列的程序處理請求。這意味着程序應該阻塞,直到隊列中有請求或者套接字上有輸入。然後它會處理請求並繼續。有沒有辦法在單線程中做到這一點?我的意思是某種select同時使用信號量和套接字。對我而言,延遲很重要,我也不想忙於等待。該程序將在Windows上運行。謝謝。有沒有辦法阻塞單個線程,直到信號量或輸入事件?

回答

1

等待幾種可能的事情之一發生的Windows方式是WaitForMultipleObjectsEx。你給它一個可以變成「信號」的Windows「句柄」數組(這些句柄稱爲同步對象),當它們中的任何一個被髮信號時,函數返回並告訴你它是哪一個。

問題是,在WinSock庫中實現的套接字不是Windows句柄。您無法將其放入WaitForMultipleObjectsEx陣列中。

幸運的是,WinSock提供的函數WSAEventSelect可以將套接字鏈接到Windows事件對象。事件對象是最簡單的同步對象類型。在這種情況下,當套接字準備好讀取時,您會要求它發出事件對象的信號(FD_READ)。然後你可以將事件對象放入數組旁邊的信號量。

Windows Semaphore已經是一個同步對象 - 請參閱MSDN中的CreateSemaphore。當它的計數大於0時就會發出信號。(這是你對信號量的期望)

如果你不理解同步對象的整體思想,並且閱讀MSDN沒有幫助,我會推薦Jim Beveridge的書多線程在Win32中的應用。這是一本舊書,所以它沒有套接字或信號量,但它解釋瞭如何使用事件對象,互斥體和一般的WaitForMultipleObjects;那麼套接字和信號量將很容易理解。

2

​​是一種抽象出I/O事件的方法,它有手動觸發事件的方法。

建立基於文件的事件與libevents看起來像這樣(從文檔複製):

void callback_func(evutil_socket_t fd, short what, void *arg) { ... } 

struct event *ev1, *ev2; 
struct event_base *base = event_base_new(); 

/* The caller has already set up fd1, fd2 somehow, and make them 
    nonblocking. */ 

ev1 = event_new(base, fd1, EV_TIMEOUT|EV_READ|EV_PERSIST, callback_func, 
    (char*)"Reading event"); 
ev2 = event_new(base, fd2, EV_WRITE|EV_PERSIST, callback_func, 
    (char*)"Writing event"); 

event_add(ev1, NULL); 
event_add(ev2, NULL); 

如果你想創建不與任何文件描述符相關聯的事件,傳遞-1這一翻譯的FD的:

ev = event_new(base, -1, EV_PERSIST | EV_READ, callback_func, NULL); 
event_add(ev, NULL); 

現在,而不是養信號,觸發事件:

event_active(ev, EV_WRITE, 0); 
3

一種方法是使用重疊I/O並使用hEvent機制來發送I/O完成信號。然後您可以使用WaitForMultipleObjects() API等待隊列信號和hEvent/s。

另一種方法是使用重疊的I/O和完成例程。然後,您可以在信號燈等待在循環與WaitForSingleObectEx() API與bAlertable參數設置爲true,使線可以處理排隊的完成例程,如:

while(WAIT_IO_COMPLETION!=WaitForSingleObjectEx(queueSema,INFINITE,true)){ 
    [deque object and handle it]; 
}; 

這兩種方案都允許您設置超時輪詢服務器保持連接打開和/或檢查它是否關閉。

相關問題