1

我无法使用 C 套接字从 Web 服务器接收“大”文件;即当这些文件(或者我怀疑)大于我用来接收它们的缓冲区的大小时。如果我尝试(通过 GET 请求)询问index.html不大于几个字节的简单内容,我会很好,但其他任何事情都会失败。我假设我缺乏知识select()或者recv()是什么让我失望。看这里:

fd_set read_fd_set;
FD_ZERO(&read_fd_set);
FD_SET((unsigned int)socketId, &read_fd_set);

/* Initialize the timeout data structure. */
struct timeval timeout;
timeout.tv_sec = 2;
timeout.tv_usec = 0;

// Receives reply from the server
int headerReceived = 0;
do {
    select(socketId+1, &read_fd_set, NULL, NULL, &timeout);

    if (!(FD_ISSET(socketId, &read_fd_set))) {
       break;
    }

    byteSize = recv(socketId, buffer, sizeof buffer, 0);

    if (byteSize == 0 || (byteSize < BUFFER_SIZE && headerReceived)) {
       break;
    }

    headerReceived = 1;

} while(1);

没错,在将 GET 请求发送到 Web 服务器之后,我很确定服务器运行良好,并且来自任何其他客户端(如任何 Web 浏览器)的 GET 请求都按预期工作。

在此先感谢,非常感谢任何帮助。

4

3 回答 3

2
if (byteSize == 0 || (byteSize < BUFFER_SIZE && headerReceived))
{
    break;
}

headerReceived在第一次读取后设置为 true。这是完全可能的,并且后续的 s可能recv()会小于BUFFER_SIZE。那时您已退出读取循环。 Recv()将返回要读取的字节数,不一定是您请求的字节数。

也要么坚持BUFFER_SIZE要么sizeof(buffer)。混合和匹配只是在路上的某个地方寻找一个错误。

于 2012-05-21T00:19:46.487 回答
1

您没有说您使用的是什么操作系统,但根据POSIX 规范

成功完成后,select () 函数可能会修改timeout参数指向的对象。

(例如,我相信 Linux 正是这样做的。)

因此,以后对循环的调用很可能会将超时设置为零,这将导致select立即返回而没有准备好描述符。

select我建议在每次通过循环调用之前立即重新初始化超时结构。

于 2012-05-21T00:08:48.470 回答
1

我发现的一件事是您没有在循环期间重新初始化选择。这可能就是您成功获取小文件的原因;一次性收到它们,并且不必重复循环。

我建议你把:

FD_ZERO(&read_fd_set);
FD_SET((unsigned int)socketId, &read_fd_set);
timeout.tv_sec = 2;
timeout.tv_usec = 0;

在循环内(在你调用之前select),它可能只是工作。

于 2012-05-21T00:27:42.717 回答