为什么最后一次read()需要很长时间才能返回

时间:2012-04-05 08:39:47

标签: c network-programming

我有一个简单的程序,它使用unix套接字从服务器下载html文件。

我使用write()发送“Get /index.html Host: * ”消息,然后使用while循环来读取() 响应。一切顺利,但最后一次读取()将返回0需要很长时间才能返回。任何想法纠正代码,以便我不必等待这个特殊的时间?或者这怎么可能发生?

    sprintf(cmdstr,"%s %s %s\r\nHOST:%s\r\n\r\n",METHOD,place,VERSION,host);
    cmdlen = strlen(cmdstr);
    if (write(sockfd,cmdstr,cmdlen) != cmdlen) {
       perror("write cmd error");
       return ;
    }

    while ((n = read(sockfd,read_data,BUFSIZE)) > 0) {
        read_data[n] = 0;
        p = read_data;

        if (filep == NULL) {
            if (filep = fopen(filename,"w")) == NULL) {
                perror("fopen ");
                return;
            }
            p = strstr(read_data,"\r\n\r\n");
            p += 4;
        }
        fputs(p,filep);
    }

    printf ("%s download completed.\n",filename);

2 个答案:

答案 0 :(得分:1)

因为您要求套接字在没有更多内容时读取BUFSIZE数据。我假设调用read阻塞等待更多数据通过TCP连接,并且只有在连接断开一段时间后才会返回。

如果你知道文件的大小,那么你可以请求只读取那么多的数据。如果您不知道文件有多大,那么您在依赖服务器在文件传输时关闭连接。

答案 1 :(得分:1)

如果没有准备好数据,recv将阻止或失败(取决于它是阻止还是非阻塞)。
当套接字的另一端关闭连接时,recv返回零。从来没有。

这通常不会发生在HTTP / 1.1(现在几乎所有现有服务器)上,至少不会立即发生,因为默认情况下连接预计会保持活动状态。

发送Connection: close向服务器发出您不希望出现此行为的信号。然后它应该尽快放弃连接(但是当你发送所有内容之后)。

或者,您可以尝试调用shutdown(sockfd, SHUT_WR);,它会执行连接的半关闭,以及服务器可能(应该,希望)对此做出适当反应。

或者,最后,您只能阅读内容长度告诉您的内容,然后删除连接,但这对服务器来说是反社会的,并且完全没有风险。