2017-02-28 15 views
2

我有一個關於將新的套接字文件描述符添加到FDSET的問題。比方說,我們已經連接到插座S1:將新的FD添加到fd_Set,同時阻止選擇

fd_set readfds; 

//s1 = socket(...); 
//connect(s1, ...)... 

FD_ZERO(&readfds); 
FD_SET(s1, &readfds); 

,我們正在等待數據回落插座,通過調用選擇中的一個線索:

socket_reader_thread() { 

    for (;;) 
    { 
     int rv = select(n, &readfds, NULL, NULL, &tv); 

     if (rv == -1) { 
     perror("select"); // error occurred in select() 
     } 
     else if (rv == 0) { 
     printf("Timeout occurred! No data after 10.5 seconds.\n"); 
     } 
     else { 
     // one the descriptors have data 
     ..... 
     } 
    } 

} 

如果我現在想添加另一個套接字(或可能是兩個更多的套接字等)到readfds集,鑑於選擇阻塞,我應該如何繼續?我怎麼能打斷選擇

是添加一個零超時和使用選擇像輪詢的技巧?

回答

3

您需要使用「管道技巧」。

這是創建附加套接字或管道的位置,將它添加到fd_set。

然後要中斷一個正在運行或未決的select,通過另一個線程向它發送一個1字節的消息。

然後,select將返回,如果特殊管道FD是集合中準備好的管道之一,那就意味着您需要查看某個列表或某個「做功」 - 就像添加任何新的FD到在返回到select調用之前的fd_set。

2

您可以通過向您的過程發送(並捕獲)信號來中斷選擇,例如使用raiseselect將在這種情況下返回-1和errno設置爲EINTR。然後,您可以更改要等待的事件,並再次撥打select

添加零超時並使用select like poll的技巧是什麼?

一個可以簡單地使用的0在這種情況下,它會只是做一個非阻塞檢查,如果任何事件的觸發得到,即輪詢超時。但是這隻能在少數情況下完成,因爲忙輪詢而不是阻塞等待會佔用很多機器資源。我甚至會考慮中斷阻塞select這是一個值得懷疑的設計,儘管可能沒有繁忙輪詢那麼糟糕。