【问题标题】:Using select and recv to obtain a file from a web server through a socket使用 select 和 recv 通过套接字从 Web 服务器获取文件
【发布时间】:2012-05-21 00:02:01
【问题描述】:

我在使用 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 请求都按预期工作。

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

【问题讨论】:

  • 我认为假设 byteSize Content-Length: 字段,告诉您标头之后有多少字节。也许 TCP 连接在传输结束时关闭(在这种情况下,recv 将返回 0) - 我不知道。

标签: c sockets


【解决方案1】:
if (byteSize == 0 || (byteSize < BUFFER_SIZE && headerReceived))
{
    break;
}

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

也可以使用BUFFER_SIZEsizeof(buffer)。混合和匹配只是在某个地方寻找错误。

【讨论】:

  • 这似乎改善了行为,谢谢!这和 EitanT 的改变相结合似乎已经成功了 :)
【解决方案2】:

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

我建议你把:

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

在循环内部(在您调用 select 之前),它可能会正常工作。

【讨论】:

  • 好吧,这似乎与 Duck 的回答相结合,谢谢!
【解决方案3】:

你没有说你用的是什么O/S,而是根据POSIX spec

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

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

因此很有可能您的循环的后续调用将超时设置为零,这将导致select 在没有准备好描述符的情况下立即返回。

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

【讨论】:

  • Linux。感谢您的建议,但不幸的是,这似乎并没有解决它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-10
  • 1970-01-01
  • 1970-01-01
  • 2015-02-16
  • 1970-01-01
  • 2017-09-13
相关资源
最近更新 更多