2012-02-06 61 views
0

我想使用read()和ioctl(),但想要通過使用超時來控制讀取應該等待的時間。 關於如何做到這一點的任何想法?如何在Unix上使用read()在C++上的套接字上使用超時

到目前爲止,我所知道的是:

//CLIENT.cpp 
struct timeval tv={1,0}; 
setsockopt(mysocket, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof(tv)); 
connect(mysocket, &sock_dest, sizeof(struct sockaddr)); 
len = read(mysocket, buffer, 10); 

我嘗試使用服務器上的一個5秒的延遲,但它沒有超時......你想要什麼

+1

您可以嘗試使用[fcntl(2)](http://linux.die.net/man/2/fcntl)設置'O_NONBLOCK',然後使用[select(2)](http:// linux。 die.net/man/2/select)找出套接字何時準備讀取(select允許您指定超時)。 – 2012-02-06 16:21:36

+0

同意。順便說一句,如果你關心'read'需要多長時間,你可能應該關心'connect'需要多長時間(如果它超時,可能會有一段時間)。在調用'connect'之前,你可以使套接字非阻塞,並通過'select'或'poll'處理。 – Useless 2012-02-06 16:25:05

回答

4

ioctl()不會做。要在讀取中使用超時,您需要使用poll()或較早的接口select()(我會使用poll())。每次收到新數據時,使用SO_RCVTIMEO設置的超時值可能會重置。所以,舉個例子,它可能會等待10秒鐘。 poll()在指定的超時後返回,告訴您是否有任何數據。一旦出現這種情況,您可以閱讀任何使用非阻塞read()的內容。

+0

我正在使用ioctl來chk多少個字節可以被讀取,如果什麼都沒有準備好,再次循環,但是讀作爲阻塞調用,使用超時繼續前進。目的是替換SELECT調用。 – maheshg 2012-02-06 16:28:43

+0

好吧,將'SO_RCTTIMEO'設置爲'timeout/size'(其中'timeout'以秒爲單位,'size'以字節爲單位)應該會產生與此類似的效果。但是,這個標誌似乎不太便於使用,如果poll()不知道是否可用,我仍然會使用poll()(或'select()')。你爲什麼要刪除這些電話?他們很好地處理超時。 – 2012-02-06 16:35:29

+0

有太多選擇調用使用相同的超時值,導致未定義的行爲,這種方式我想實現重試,並管理超時...... – maheshg 2012-02-06 16:49:17

0

你確定它在讀取時被阻塞,還是可能在connect()上阻塞?我不相信SO_RCVTIMEO(和SO_SNDTIMEO)選項會影響connect()行爲。通常,我喜歡使用非阻塞套接字(帶有O_NONBLOCK的fcntl),然後捕獲EWOULDBLOCK錯誤號並使用讀集中的套接字和期望的超時執行select()。

2

您可以通過設置鬧鐘來完成您想要的任務,以中斷系統調用。你需要一些基本的設置在某處主要還是在你的程序初始化過程的早期階段:

#include <signal.h> 

sig_atomic_t alarm_counter; 

void alarm_handler(int signal) { 
    alarm_counter++; 
} 

void setup_alarm_handler() { 
    struct sigaction sa; 
    memset(&sa, 0, sizeof(sa)); 
    sa.sa_handler = alarm_handler; 
    sa.flags = 0; 
    if (sigaction(SIGALRM, &sa, 0) < 0) 
     die("Can't establish signal handler"); 
} 
// call setup_alarm_handler in main 

然後,你可以用它喜歡:

alarm(10); // set a 10 second timeout 
(len = connect(mysocket, &sock_dest, sizeof(struct sockaddr))) < 0 || 
(len = read(mysocket, buffer, 10)); 
alarm(0); // cancel alarm if it hasn't happened yet 
if (len == -1 && errno == EINTR) 
    // timed out before any data read 
else if (len == -1) 
    // other error 

這樣你可以有一個超時調用序列(如果連接或讀取時間過長或者總共需要太長時間,這會超時),而不是必須弄清楚每次通話所花費的時間,因此您知道等待每個後續呼叫需要多長時間。

相關問題