gpt4 book ai didi

c++ - HttpSendRequest 未从服务器获取最新文件

转载 作者:行者123 更新时间:2023-11-28 03:57:55 26 4
gpt4 key购买 nike

我的应用程序中的 HTTP 请求出现问题,如果远程文件与本地文件大小相同(即使其修改时间不同,因为其内容已更改),尝试下载它很快返回并且没有下载较新的文件。

简而言之,我遵循的过程是:使用 INTERNET_FLAG_RESYNCHRONIZE 标志设置 HTTP 连接并调用 HttpSendRequest();然后检查 HTTP 状态代码,发现它是“200”。

  • 如果远程文件已更新,但与本地拷贝大小保持不变:运行应用后本地文件未更改。如果我在发送请求后用 HTTP_QUERY_LAST_MODIFIED 调用 HttpQueryInfo(),它会给我服务器文件的实际最后修改时间,我可以看到它与本地文件不同我正在尝试覆盖它。
  • 如果更新了远程文件,并且文件大小变得与本地拷贝不同:它会按预期下载并覆盖本地拷贝。

这是代码的一个相当精简的版本,删除了帮助程序和错误检查:

// szAppName = our app name
HINTERNET hInternetHandle = InternetOpen( szAppName,
INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
// szServerName = our server name
hInternetHandle = InternetConnect( hInternetHandle, szServerName,
INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, NULL, 0 );

// szPath = the file to download
LPCSTR aszDefault[2] = { "*/*", NULL };
DWORD dwFlags = 0
| INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP
| INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS
| INTERNET_FLAG_KEEP_CONNECTION
| INTERNET_FLAG_NO_AUTH
| INTERNET_FLAG_NO_AUTO_REDIRECT
| INTERNET_FLAG_NO_COOKIES
| INTERNET_FLAG_NO_UI
| INTERNET_FLAG_RESYNCHRONIZE;
HINTERNET hHandle = HttpOpenRequest( hInternetHandle, "GET", szPath, NULL,
NULL, aszDefault, dwFlags, 0 );

DWORD dwTimeOut = 10 * 1000; // In milliseconds
InternetSetOption( hInternetHandle, INTERNET_OPTION_CONNECT_TIMEOUT,
&dwTimeOut, sizeof( dwTimeOut ) );
InternetSetOption( hInternetHandle, INTERNET_OPTION_RECEIVE_TIMEOUT,
&dwTimeOut, sizeof( dwTimeOut ) );
InternetSetOption( hInternetHandle, INTERNET_OPTION_SEND_TIMEOUT,
&dwTimeOut, sizeof( dwTimeOut ) );
DWORD dwRetries = 5;
InternetSetOption( hInternetHandle, INTERNET_OPTION_CONNECT_RETRIES,
&dwRetries, sizeof( dwRetries ) );

HttpSendRequest( hInternetHandle, NULL, 0, NULL, 0 );

因为我发现我可以查询远程文件的最后修改时间,并且发现它是准确的,所以我知道它实际上正在到达服务器。我认为指定 INTERNET_FLAG_RESYNCHRONIZE 会强制文件为 resynch if it's out of date .我都错了吗?这就是它应该的工作方式吗?


编辑:我用数据包嗅探器做了一些调查,这里有一些额外的信息:

如果远程文件和本地文件完全一样,这就是交换:

GET /test.bmp HTTP/1.1
Accept: */*
If-None-Match: "1c1467112ee6ca1:369"
User-Agent: Internal Testing
Host: ****************
Connection: Keep-Alive

HTTP/1.1 304 Not Modified
Last-Modified: Tue, 27 Apr 2010 17:21:26 GMT
Accept-Ranges: bytes
ETag: "1c1467112ee6ca1:369"
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Tue, 27 Apr 2010 18:10:26 GMT

现在,如果远程文件已更改,但文件大小保持不变:

GET /test.bmp HTTP/1.1
Accept: */*
If-None-Match: "1c1467112ee6ca1:369"
User-Agent: Internal Testing
Host: ****************
Connection: Keep-Alive

HTTP/1.1 200 OK
Content-Length: 419958
Content-Type: image/bmp
Last-Modified: Tue, 27 Apr 2010 18:11:17 GMT
Accept-Ranges: bytes
ETag: "b65425835e6ca1:369"
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Tue, 27 Apr 2010 18:11:33 GMT
[Block of data]

所以,服务器确实在文件发生变化时发送文件,但我的应用程序似乎仍然认为它没有发生变化。我认为问题在于我的应用程序如何处理响应;这不是我自己的代码,编写它的人很久以前就离开了。

我发现的一个问题是,在上述两种情况下,当我使用HTTP_QUERY_STATUS_CODE 调用HttpQueryInfo() 时,我得到 200后退。但是,在上面的第一种情况下,我可以看到实际的服务器响应是 304,而不是 200。深入研究我们正在使用的代码,我发现它似乎试图通过文件大小比较来解决这个问题,并假设如果文件大小相同,文件没有改变;因此,我遇到了问题!

所以现在我的问题更简单了:为什么即使服务器返回 3XX 错误之一,HttpQueryInfo() 也会返回 200?我发现有些人在网上问类似的问题,但他们要么 received no responses或者直接与网络浏览器打交道。

最佳答案

我相信 INTERNET_FLAG_RESYNCHRONIZE 使用 If-Modified-Since HTTP 请求 header 字段并检查状态代码,而 HTTP_QUERY_LAST_MODIFIED 将(我认为)只是执行 HEAD 请求 &检查 HTTP 响应 Last-Modified header 字段。

尝试使用 HTTP_QUERY_IF_UNMODIFIED_SINCEHTTP_QUERY_LAST_MODIFIEDHttpQueryInfo() 并比较结果 [如果您有 HTTP 嗅探器,请作为旁注运行它可能会为我们所有人清除一些问题...]。

作为一种快速而肮脏的解决方案,您可以使用 INTERNET_FLAG_RELOAD 而不是 INTERNET_FLAG_RESYNCHRONIZE 来强制文件在每次请求时重新加载。

HTH

关于c++ - HttpSendRequest 未从服务器获取最新文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2655102/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com