如果MacBook睡眠时间超过10分钟,则“读”挂

时间:2009-11-04 08:30:52

标签: macos sockets network-programming

我正在编写一个应用程序,其中套接字连接到主机并下载文件。 该应用程序在Mac中运行。

现在,当应用程序正在下载时,如果我将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?

2 个答案:

答案 0 :(得分:1)

TCP / IP连接不能在睡眠模式下运行。 SO_KEEPALIVE在这种情况下无效,因为它对服务器端没有影响。等待两分钟,阅读将超时。超时后,您可以再次连接。

sleep(1)是不必要的。一旦数据可用,服务器将立即响应。如果你没有立即获取,你将在服务器上分配一个超过你需要的连接。

答案 1 :(得分:0)

我无法使用阻塞套接字来解决它。我不得不将IMAP库更改为非阻塞套接字。