c++ - 使用 TCP 连接从 HTTP 服务器获取数据,在极少数情况下会出现垃圾数据

标签 c++ tcp http-headers winsock2 winsockets

我正在使用 C++ 使用 Winsocks 2.2 和 Visual Studio 2010 编写一个网络游戏,并决定使用我的网络服务器来存储游戏的事件服务器列表是个好主意。当服务器启动时,它会在我的网络服务器上注册自己,退出时取消注册;当有人访问服务器列表时,服务器本身将尝试清理列表(我仍在努力设计这种行为,以免在服务器上涉及太多工作;但我想当游戏服务器尝试添加自己时,我的php 文件将使用 fsockopen 来检测它是否真的可以从外部网络访问服务器,如果不能,则在它可以正确设置端口转发或以某种方式解决问题之前不会添加服务器)。

好吧,经过一些研究,我想出了如何使用 TCP 连接从服务器获取某些东西,方法是为 HTTP 服务器格式化一条专门的消息。这是我拥有的:

if(FAIL == Connection::Get_Connection(&m_Connection, networkSettings.ServerListAddress, 80))
{
    return FAIL;
}

m_Connection.SendMsg("GET /servers.php HTTP/1.1\r\nHost: cyclotron.leetnightshade.com\r\nUser-Agent: CycloTron\r\n\r\n");

我期待返回格式正确的数据,但我并没有完全得到。这是我得到的:

2f
Server Count:1
129.21.138.1,40000,Depth of Hell
0

这是带有所有 header 信息的一些垃圾的另一个输出:

HTTP/1.1 200 OK
Date: Tue, 12 Apr 2011 23:23:11 GMT
Server: Apache
X-Powered-By: PHP/5.2.17
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: PHPSESSID=8254688ee345202bd177d57e4ba339b2; path=/
Set-Cookie: PHPSESSID=73eae89f61e7268f433af9bdfe299173; path=/
Set-Cookie: PHPSESSID=8fb5d6fd9f1023bb00290b4daa3c7952; path=/
Connection: close
Transfer-Encoding: chunked
Content-Type: text; charset=us-ascii

e
Server Count:1
21

129.21.138.1,40000,Depth of Hell
0

这就是我的输出应该看起来的样子,我偶尔会得到这个,但并非总是如此:

HTTP/1.1 200 OK
Date: Tue, 12 Apr 2011 23:32:13 GMT
Server: Apache
X-Powered-By: PHP/5.2.17
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: PHPSESSID=a3c88c2d96d45c6f6d3b029e095c429a; path=/
Set-Cookie: PHPSESSID=bf19734ff60813d6d0a5ba944410356a; path=/
Set-Cookie: PHPSESSID=c36a2d9e12c81d4a19a7f41dc5522b4e; path=/
Content-Length: 47
Connection: close
Content-Type: text; charset=us-ascii

Server Count:1
129.21.138.1,40000,Depth of Hell

我认为这无关紧要,但这是我在网络服务器上的 PHP 代码:

$num = mysql_num_rows($result);
echo 'Server Count:'.$num;

while ($row = mysql_fetch_assoc($result))
{
    // TODO: check date of entry, if it's really old, remove it.
    echo PHP_EOL.$row['address'].','.$row['port'].','.$row['displayName'];
}

这里是一些涉及接收字符串的代码(是的,目前它只是一些简单的骨头,我意识到我可以使用 cstring 函数来查找两个新行,所以我不必做字符串复制,我只是想坚持使用字符串来使事情变得更容易):

memset(m_MsgBuffer, 0, sizeof (char) * M_BufferSize);

m_Received = recv(m_Connection.M_Socket, m_MsgBuffer, M_BufferSize, 0);

m_MsgBuffer[m_Received] = '\0';

string str = string(m_MsgBuffer);

size_t index = str.find("\r\n\r\n");
str.erase(0,index);

std::cout << "Received message: " << str << std::endl;

那么,你们中有人知道这些垃圾数据是从哪里来的吗?

编辑:查看正确的 header 信息后,带有垃圾的 header 具有“Transfer-Encoding: chunked”并且没有“content-length”。 ...发生了什么事?

最佳答案

所谓“垃圾”,其实就是来自服务器的分 block 数据。如果 HTTP/1.1 服务器愿意,它可以自由地以分 block 格式发回数据,并且 HTTP/1.1 规范非常明确:“所有 HTTP/1.1 应用程序必须能够接收和解码“分 block ”传输编码” .

分 block 编码的细节在 HTTP/1.1 规范中有描述:

http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1

如果您正在编写 HTTP 客户端,则需要阅读 HTTP 规范...

关于c++ - 使用 TCP 连接从 HTTP 服务器获取数据,在极少数情况下会出现垃圾数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5642798/

相关文章:

http - 浏览器图片缓存困惑

c++ - 将 std::string 解释为 char_type 的 std::vector?

c++ - 如何在编译时构建有向图?

c++ - 如何在 QThread 中运行定时器?

python - 我需要服务器向所有客户端发送消息(Python、套接字)

linux - 最佳 TCP 发送缓冲区大小

http - HTTP 部分 GET 是一种可靠的机制吗?

c++ - 寻找一个点的 "movement direction"(角度)

sockets - UDP 数据包可以像 TCP 一样部分发送吗?

http - http 响应中没有 Cache-Control header 的 ETag