2013-07-23 61 views
5

我試圖檢測客戶端與select()函數斷開連接時。問題是,我不太瞭解select()是如何工作的。我使用下面的代碼,你能告訴我我做錯了什麼和/或如何檢測客戶端是否斷開連接? 我正在使用非阻塞套接字。檢測套接字斷開使用select()

int Network::bytesAvailable() 
{ 
    long bytes = 0; 

    if(ioctl(this->sockfd, FIONREAD, &bytes) < 0) 
    { 
     printf("ERROR: Network:bytesAvailable: ioctl() call failed.\n"); 
     return -1; 
    } 

    return bytes; 
} 

NetworkStatus Network::status() 
{ 
    struct timeval tv; 
    fd_set fd; 
    int result = 0; 

    tv.tv_sec = 5; 
    tv.tv_usec = 0; 

    FD_ZERO(&fd); 
    FD_SET(this->sockfd, &fd); 

    result = select(this->sockfd + 1, &fd, 0, 0, &tv); 

    if(result && !this->bytesAvailable()) 
    { 
     return -1; // disconnected, I'm guessing this is definitely WRONG. 
    } 
    else if(result > 0 && FD_ISSET(this->sockfd, &fd)) 
    { 
     return 1; // bytes available. 
    } 
    else if(!result) 
    { 
     return 0; // timeout 
    } 

    return -1; // select() call failed. 
} 
+0

一般我們檢測到,無論連接是否存活?使用'keepalive'和'select()'我們用於複用。它不是**正確嗎? –

+0

我不明白你的語法,對不起:) – user2399415

+0

對不起我的英文很差:(但我編輯過評論,我現在明白了嗎? –

回答

8

當套接字關閉時它變成「可讀」,但調用recv將返回0字節。使用select你可以知道什麼時候可以讀取套接字,然後在讀取它時如果recv返回0,那麼你知道它已經關閉。

您的評論「字節可用」並不完全準確。但是,可以讀取套接字,如果它關閉,則不會有字節可用。

else if(result > 0 && FD_ISSET(this->sockfd, &fd)) 
{ 
    return 1; // bytes available. 
} 

在非阻塞插座,recv將返回-1,並設置errnoEWOULDBLOCK(或EAGAIN)如果沒有數據和插座未關閉。

+0

AFAIK on non-blocking sockets ,這是不正確的,因爲recv可以返回0(尚未收到數據)。 – user2399415

+0

檢查我的編輯有關非阻塞套接字。 –

+0

謝謝。問題解決了。 – user2399415