2009-11-04 66 views
1

我正在編寫一個應用程序,其中套接字連接到主機並下載文件。 該應用程序在Mac中運行。如果MacBook睡眠超過10分鐘,套接字「讀取」掛起

現在,當應用程序正在下載時,如果我將MacBook置於睡眠模式超過10分鐘,則當計算機被喚醒時,應用程序掛起的時間有60%。

堆棧跟蹤顯示,它在「讀取」調用中被掛起。我能夠通過一個示例程序來重現這一點。下面,我粘貼了示例程序的代碼以及它掛起的堆棧。如何解決這個掛?

此外,這不僅僅是在幾分鐘內出現的TCP/IP等待。我等了超過12個小時,沒有出來。

堆棧跟蹤: -

Call graph: 
    2466 Thread_2507 
     2466 start 
     2466 read$UNIX2003 
      2466 read$UNIX2003 

程序: -

#include <stdio.h> 
#include <string.h> 
#include <netdb.h> 
#include <sys/socket.h> 
#include <unistd.h> 

#define buflen 131072 
unsigned int portno = 80; 
char hostname[] = "192.168.1.9"; 

int main() 
{ 
    int sd = socket(AF_INET, SOCK_STREAM, 0); /* init socket descriptor */  
    struct sockaddr_in sin; 
    struct hostent *host = gethostbyname(hostname); 
    char buf[buflen]; 
    int len; 
    int ret; 
    FILE *fp; 
    int i; 

    if(sd == -1){ 
     printf("Could not create client socket\n"); 
     return 1; 
    } 

    /*set keep alive*/ 
    int optval = 1; 
int optlen = sizeof(optval); 
    ret = setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen); 
    if(ret != 0){ 
     printf("could not set socket option.\n"); 
     return 1; 
    } 

    /*** PLACE DATA IN sockaddr_in struct ***/ 
    memcpy(&sin.sin_addr.s_addr, host->h_addr, host->h_length); 
    sin.sin_family = AF_INET; 
    sin.sin_port = htons(portno); 

    /*** CONNECT SOCKET TO THE SERVICE DESCRIBED BY sockaddr_in struct ***/ 
    if (connect(sd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 
     perror("connecting"); 
     return 1; 
    } 

    char *str = "GET /general-log.exe/HTTP/1.0\n\n"; 

    ret = write(sd, str, strlen(str)); 
    if(ret < 0){ 
     printf("error while writing\n"); 
     return 1; 
    } 


    fp = fopen("downloaded.file", "wb+"); 
    if(fp == NULL){ 
     printf("not able to open the file.\n"); 
     return 1; 
    } 

    i = 0; 
    while ((len = read(sd, buf, buflen)) > 0) {   
     printf("%d\t%d\n", i++, len); 
     fwrite(buf, len, 1, fp); //we should check for return 
    } 
    if(len < 0){ 
     printf("Error while reading\n"); 
    } 

    fclose(fp); 
    close(sd); 
    return 0; 
} 

更新顯然SO_RCVTIMEOUT是解決這個問題。

struct timeval tv; 
tv.tv_sec=10; 
tv.tv_usec=0; 
setsockopt (m_sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof (tv)); 

可以使用SO_RCVTIMEO嗎?

回答

0

我無法使用阻塞套接字解決它。我不得不將IMAP庫更改爲非阻塞套接字。

1

TCP/IP連接無法在睡眠模式下存活。 SO_KEEPALIVE在這種情況下不起作用,因爲它對服務器端沒有任何影響。等待兩分鐘,閱讀將超時。超時後,您可以重新連接。

而且sleep(1)是不必要的。只要數據可用,服務器將立即響應。如果您不立即獲取,您將在服務器上分配連接的時間超過您的需要。

+0

謝謝。更新了我的問題。 – Sabya 2009-11-04 08:37:26

+0

SO_KEEPALIVE在這種情況下不起作用,因爲它對服務器端沒有任何影響。 – 2009-11-04 08:57:53

+0

我已經等了12個多小時,程序沒有出來。 – Sabya 2009-11-04 09:18:24