我尝试使用C ++实现一个简单的HTTP服务器。我能够将文本响应发送到浏览器,但是无法发送二进制文件请求的响应。
这是我的代码,用于获取对PNG文件请求的HTML响应:
string create_html_output_for_binary(const string &full_path)
{
const char* file_name = full_path.c_str();
FILE* file_stream = fopen(file_name, "rb");
string file_str;
size_t file_size;
if(file_stream != nullptr)
{
fseek(file_stream, 0, SEEK_END);
long file_length = ftell(file_stream);
rewind(file_stream);
// Allocate memory. Info: http://www.cplusplus.com/reference/cstdio/fread/?kw=fread
char* buffer = (char*) malloc(sizeof(char) * file_length);
if(buffer != nullptr)
{
file_size = fread(buffer, 1, file_length, file_stream);
stringstream out;
for(int i = 0; i < file_size; i++)
{
out << buffer[i];
}
string copy = out.str();
file_str = copy;
}
else
{
printf("buffer is null!");
}
}
else
{
printf("file_stream is null! file name -> %s\n", file_name);
}
string html = "HTTP/1.1 200 Okay\r\nContent-Type: text/html; charset=ISO-8859-4 \r\n\r\n" + string("FILE NOT FOUND!!");
if(file_str.length() > 0)
{
// HTTP/1.0 200 OK
// Server: cchttpd/0.1.0
// Content-Type: image/gif
// Content-Transfer-Encoding: binary
// Content-Length: 41758
string file_size_str = to_string(file_str.length());
html = "HTTP/1.1 200 Okay\r\nContent-Type: image/png; Content-Transfer-Encoding: binary; Content-Length: " + file_size_str + ";charset=ISO-8859-4 \r\n\r\n" + file_str;
printf("\n\nHTML -> %s\n\nfile_str -> %ld\n\n\n", html.c_str(), file_str.length());
}
return html;
}
此代码成功读取文件并将数据存储在char* buffer
上。令我感到困惑的是,尽管file_str
总是包含\211PNG
,但是当我检查其大小时,却比\211PNG
大得多。我怀疑这是导致我的图像未加载到浏览器中的问题,因为当我打印HTML时,它仅显示:
HTTP/1.1 200 Okay
Content-Type: image/png; Content-Transfer-Encoding: binary; Content-Length: 187542;charset=ISO-8859-4
\211PNG
我在想将二进制数据发送到浏览器的方式与发送文本数据的方式相同,因此我首先创建字符串标题,然后读取文件数据,将其转换为字符串并与标题组合,然后最后发送一个大的HTTP套接字的单个字符串。
我也尝试过此代码:
if (file_stream != NULL)
{
short stringlength = 6;
string mystring;
mystring.reserve(stringlength);
fseek(file_stream , 0, SEEK_SET);
fread(&mystring[0], sizeof(char), (size_t)stringlength, file_stream);
printf("TEST -> %s, length -> %ld\n", mystring.c_str(), mystring.length());
fclose(file_stream );
}
但是HTML输出始终相同,并且在打印时mystring
也仅包含\211PNG
。
我走错了路吗?请帮助找出我的代码中的错误。谢谢。
您正在将数据大块地存储到std::stringstream
中。这将不起作用,因为值零将被解释为空终止符。这将导致忽略空终止符之后的所有内容。您应该使用std::vector
之类的容器来存储和管理二进制数据。
#include <vector>
string create_html_output_for_binary(const string &full_path)
{
std::vector<char> buffer;
//... other code here
if(ile_stream != nullptr)
{
fseek(file_stream, 0, SEEK_END);
long file_length = ftell(file_stream);
rewind(file_stream);
buffer.resize(file_length);
file_size = fread(&buffer[0], 1, file_length, file_stream);
}
// .... other code here
}
要输出数据,请不是使用printf
。它可能以不同的方式处理新行,并将在遇到第一个空终止符时停止。而是(与使用C流IO保持一致)使用fwrite
。
fwrite (buffer.data(), 1 , buffer.size() , stdout );
为了使上述功能正常工作,您需要重新打开以二进制模式写入的stdout
。 Stackoverflow上的This answer显示了如何完成此操作。这只是将内容输出到stdout
,因为您正在通过套接字传输日期,所以您无需对stdout
进行任何操作。
首先,您需要打开文件(您的图片所在的位置)以读取二进制文件。