2010-05-20 140 views
80

我怎樣才能嘗試從超時套接字讀取數據? 我知道,select,pselect,poll,有一個超時字段,但是使用它們會禁用tcp reno棧中的「tcp fast-path」。Linux:有沒有從超時套接字讀取或recv?

我唯一的想法是使用的recv(FD,...,MSG_DONTWAIT)在一個循環

+0

也有使用線程的選擇:)但信號線仍然需要 – osgx 2010-06-04 13:36:05

回答

147

可以使用setsockopt函數來設置超時的接收操作:

SO_RCVTIMEO

設置指定 輸入 功能等待,直到它的最大時間量的超時值完成。它 接受與 秒數和微秒 指定上多久 等待極限,用於將輸入到操作完成 以timeval結構。如果接收操作已阻塞爲 這麼多時間而不 接收附加數據,應當 返回與部分計數或errno 設置爲[EAGAIN]或者如果沒有 數據被接收[EWOULDBLOCK]。此 選項的默認值爲零,這表示 接收操作不應超時。 該選項採用timeval結構。 請注意,並非所有實施 都允許設置此選項。

// LINUX 
struct timeval tv; 
tv.tv_sec = timeout_in_seconds; 
tv.tv_usec = 0; 
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); 

// WINDOWS 
DWORD timeout = timeout_in_seconds * 1000; 
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout); 

// MAC OS X (identical to Linux) 
struct timeval tv; 
tv.tv_sec = timeout_in_seconds; 
tv.tv_usec = 0; 
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv); 

Reportedly在Windows這應該叫bind之前完成。我已經通過實驗證實,它可以完成之前或bind在Linux和OS X.後

+2

它是否適用於Linux 2.6 tcp? UDP? – osgx 2010-05-31 12:16:58

+5

是的。非常感謝 – osgx 2010-06-04 13:33:48

+0

這在Windows上看不到。 – Mendes 2016-04-15 18:32:06

0

SIGALRM安裝一個處理程序,那麼之前經常阻塞recv()使用alarm()ualarm()。如果警報消失,recv()將返回一個錯誤errno設置爲EINTR

+8

報警(和信號)是錯誤的方式本任務。如果我想使用tcp快速路徑,比我需要最小的延遲。信號很慢。 – osgx 2010-06-04 13:35:17

+1

@osgx信號僅在超時時發生。 – 2015-11-03 23:04:30

13

這裏有一個簡單的代碼在C添加時間來使用輪詢您的recv函數:

struct pollfd fd; 
int ret; 

fd.fd = mySocket; // your socket handler 
fd.events = POLLIN; 
ret = poll(&fd, 1, 1000); // 1 second for timeout 
switch (ret) { 
    case -1: 
     // Error 
     break; 
    case 0: 
     // Timeout 
     break; 
    default: 
     recv(mySocket,buf,sizeof(buf), 0); // get your data 
     break; 
} 
-1

LINUX

struct timeval tv; 
tv.tv_sec = 30;  // 30 Secs Timeout 
tv.tv_usec = 0;  // Not init'ing this can cause strange errors 
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval)); 

WINDOWS

DWORD timeout = SOCKET_READ_TIMEOUT_SEC * 1000; 
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout)); 

注意:你已經把這個設置之前bind()函數調用正確的運行

+2

這個問題已經在幾年前回答了。你的解決方案帶來了什麼新的價值? – 2017-08-30 10:39:32

+0

你已經把這個設置放在bind()函數調用之前,正確運行這部分在ans裏沒有提到 – vivek 2017-09-08 10:17:58

相關問題