我正在为我的第一个用 C++ 编写的程序创建一个更新机制。 理论是:
- 程序将它的版本作为 http header 发送到服务器 php
- 服务器检查是否存在更新版本
- 如果是,服务器将新的二进制文件发送给客户端。
大部分都有效,但是收到的二进制文件格式不正确。当我将格式错误的 exe 与工作的 exe 进行比较时,我在编译的 exe 中有 \r\n
的地方有差异。似乎 \r
加倍了。
我的c++下载代码:
void checkForUpdates () {
SOCKET sock = createHttpSocket (); // creates the socket, nothing wrong here, other requests work
char* msg = (char*)"GET /u/2 HTTP/1.1\r\nHost: imgup.hu\r\nUser-Agent: imgup uploader app\r\nVersion: 1\r\n\r\n";
if (send(sock, msg, strlen(msg), 0) == SOCKET_ERROR) {
error("send failed with error\n");
}
shutdown(sock, SD_SEND);
FILE *fp = fopen("update.exe", "w");
char answ[1024] = {};
int iResult;
bool first = false;
do {
if ((iResult = recv(sock, answ, 1024, 0)) < 0) {
error("recv failed with error\n");
}
if (first) {
info (answ); // debug purposes
first = false;
} else {
fwrite(answ, 1, iResult, fp);
fflush(fp);
}
} while (iResult > 0);
shutdown(sock, SD_RECEIVE);
if (closesocket(sock) == SOCKET_ERROR) {
error("closesocket failed with error\n");
}
fclose(fp);
delete[] answ;
}
和我的 php 来处理请求
<?php
if (!function_exists('getallheaders')) {
function getallheaders() {
$headers = '';
foreach ($_SERVER as $name => $value) {
if (substr($name, 0, 5) == 'HTTP_') {
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
}
}
return $headers;
}
}
$version = '0';
foreach (getallheaders() as $name => $value) {
if (strtolower ($name) == 'version') {
$version = $value;
break;
}
}
if ($version == '0') {
exit('error');
}
if ($handle = opendir('.')) {
while (false !== ($entry = readdir($handle))) {
if ($entry != '.' && $entry != '..' && $entry != 'u.php') {
if (intval ($entry) > intval($version)) {
header('Content-Version: ' . $entry);
header('Content-Length: ' . filesize($entry));
header('Content-Type: application/octet-stream');
echo "\r\n";
ob_clean();
flush();
readfile($entry);
exit();
}
}
}
closedir($handle);
}
echo 'error2';
?>
请注意我发送 header 后刷新内容的方式 ob_clean(); flush();
所以我不必在 C++ 中解析它们。写入文件的第一个字节没问题,所以我怀疑这里有什么问题。
此外,二进制文件的示例比较 http://i.imgup.hu/meC16C.png
问题:http 是否在二进制文件传输中转义\r\n
?如果不是,是什么导致了这种行为,我该如何解决这个问题?
最佳答案
fopen
以您指定的模式打开一个文件,首先是读/写/两者,然后是追加,然后是二进制标识符。
r/w 你应该很清楚,append 也很明显。您的情况下的技巧与麻烦是二进制模式。
如果文件被威胁为文本文件(没有“b”),那么,根据应用程序运行的环境,文本模式下的输入/输出操作可能会发生一些特殊字符转换,以使其适应系统特定的文本文件格式。在 Windows 上,这将是\r\n,在 linux 机器上,你有\n,在某些存在的体系结构上,它是\r。
在您的例子中,输入文件被读取为文本文件。这意味着,当从 HTTP-Data 读取文件时,所有的行尾都会被转换。
将文件作为二进制文件打开(确实是!)避免了您的文件不再是二进制文件的麻烦。
关于php - C++ 从 http 下载二进制文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16886180/