【问题标题】:Weird behavior in an HTTP request with Winsock2使用 Winsock2 的 HTTP 请求中的奇怪行为
【发布时间】:2013-09-04 08:36:56
【问题描述】:

我正在尝试使用 winsock 2 在 C++ 中实现 HTTP 请求。

连接http://stackoverflow.com后, 这是我发送的内容:

send(_socket, "GET / HTTP/1.1\r\nHost: www.stackoverflow.com\r\n\r\n", (the length ), 0);

现在阅读回复:

std::string s;
char buffer[BUFFER_LENGTH];
int bytes = 0;

do
{
    ZeroMemory(buffer, BUFFER_LENGTH);
    bytes = recv(_socket, buffer, BUFFER_LENGTH, 0);
    s.append(buffer);
} while (bytes == BUFFER_LENGTH);

return s;

顺便说一句:#define BUFFER_LENGTH 512

奇怪的部分来了,当我运行程序时,我只得到响应的标题部分:

HTTP/1.1 200 OK

Cache-Control: public, max-age=34

Content-Type: text/html; charset=utf-8

Expires: Wed, 04 Sep 2013 08:14:00 GMT

Last-Modified: Wed, 04 Sep 2013 08:13:00 GMT

Vary: *

X-Frame-Options: SAMEORIGIN

Date: Wed, 04 Sep 2013 08:13:26 GMT

Content-Length: 193288

但是当我一步步调试读取函数时,我得到了包括内容在内的所有响应。如果我将断点放在 ZeroMemory() 函数上,然后按 F10 键(Step Over)继续执行代码,一次推进一个“命令”,循环继续几次然后存在并返回完整响应, 标题和内容。但是,如果我将断点放在 recv() 函数 (s.append(buffer)) 之后,则循环立即存在(仅在执行一次循环之后)并仅重新运行标题。

有人可以向我解释这种行为吗?

我假设在发送标头和内容之间存在某种定时延迟,因此当我在使用调试器的 recv() 之前停止时,服务器有足够的时间发送它,然后再发送 recv()可以全部读取,但是当我把它放在后面时,服务器只有足够的时间发送标头,recv() 函数只读取已经到达的内容,然后返回读取的少于 512 个字节,并且循环存在。我说的对吗?

提前致谢!

【问题讨论】:

  • 重新阅读recv的文档。您可以获得较少的阅读量。
  • 你真的应该检查错误或关闭的连接(即当bytes <= 0时)。另请记住,如果目前没有更多可用数据,recv 可以读取少于请求。
  • 你看到不同行为取决于断点位置的原因是,如果你把断点放在recv之前或之前,内部winsock缓冲区将有时间在你之前填满按 F10,因此当您执行 recv 时,更有可能(但不确定)您将获得请求的数据量。

标签: c++ http winsock2


【解决方案1】:

假设是正确的,如评论中所述,如果数据尚未到达,您可以获得小于缓冲区大小的数据。您在循环中应该做的实际上是使用 HTTP 知识,例如查找 \r\n\r\n 以了解标头何时到达,然后查找内容长度并尝试读取内容的数据量。或者,由于您已经在 Winsock2 上使用他们的方法 HttpSendRequest (http://msdn.microsoft.com/en-us/library/windows/desktop/aa384247(v=vs.85).aspx) 和朋友 - 如果您只想发送请求,问题就更少了。

【讨论】:

  • 好主意,我试着用这种方式解析它!而且我不想使用这个函数,因为它是特定于 winsock 的,我希望代码是可移植的。
猜你喜欢
  • 2011-02-02
  • 2013-06-24
  • 2017-09-01
  • 1970-01-01
  • 2020-03-02
  • 2020-05-07
  • 2020-08-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多