我正在尝试创建一个Web服务器来了解HTTP的功能。我正在尝试将png文件发送到浏览器,但是图像成功实现了它。
这是我的png发送代码:
std::ifstream in("P:/server"+location, std::ios::binary);
if(!in.is_open()) {
std::cout << "failed to open file" << std::endl;
in.close();
}
in.seekg(0, std::ios::end);
int length = in.tellg();
in.seekg(0, std::ios::beg);
char *data = new char[length];
in.read(data, length);
in.close();
std::string headers = "HTTP/1.1 200 OK\n\rContent-Length: " + std::to_string(length) + "\n\rConnection: keep-alive\n\rContent-Type: image/png\n\r\n\r";
int totalLength = headers.length() + length;
char *allData = new char[totalLength];
std::strcpy(allData, headers.data());
std::strcat(allData, data);
int bytes = send(socket, data, totalLength, NULL);
服务器应该发送图像后,它会显示为丢失的图像图标。
我已经检查过以确保正在发送所有字节,并且正在加载图像。 非常感谢任何帮助!
答案 0 :(得分:0)
您的代码中存在相当多的错误。
如果is_open()
返回false,您仍在尝试处理该文件。
当您需要使用\n\r
时,您正在使用\r\n
。
您正在使用strcat()
向data
追加allData
。当附加二进制数据(如PNG)时,strcat()
将在遇到的第一个0x00
字节上截断。您需要使用memcpy()
(或等效的)。
当send()
发送data
时,allData
的来电正在发送data
。因此,您根本不发送HTTP标头,而是使用错误的长度发送send()
。
您假设send()
将在一次操作中发送您提供的所有数据。几乎从来没有这种情况,尤其是大量数据。 allData
返回它实际接受发送的字节数,因此您需要在循环中调用它,直到所有数据都被接受为止。
如果在准备文件时出现问题,您不会向客户端发送错误消息。
话虽如此,headers
实际上是不必要的,浪费了记忆。 TCP是一个字节流,因此您可以依次单独发送data
和send()
。您拨打data
的次数并不会影响对方接收数据的方式。
您还可以考虑通过将send()
更改为固定大小的缓冲区来进一步减少内存使用量,以便在以较小的块读取时in
int sendData(int sckt, const void *data, int datalen)
{
const char *ptr = static_cast<const char*>(data);
while (datalen > 0) {
int bytes = send(sckt, ptr, datalen, 0);
if (bytes <=0) return -1;
ptr += bytes;
datalen -= bytes;
}
return 0;
}
int sendStr(int sckt, const std::string &s)
{
return sendData(sckt, s.c_str(), s.size());
}
...
std::string filename = "P:/server"+location;
if (!fileExists(filename)) // <- you need to implement this
{
if (sendStr(socket, "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n") == -1) {
close(socket);
}
}
else
{
std::ifstream in(filename, std::ios::binary);
if (!in.is_open())
{
std::cout << "failed to open file" << std::endl;
if (sendStr(socket, "HTTP/1.1 500 Error\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n") == -1) {
close(socket);
}
}
else
{
in.seekg(0, std::ios::end);
std::size_t length = in.tellg();
in.seekg(0, std::ios::beg);
if (in.fail())
{
std::cout << "failed to get size of file" << std::endl;
if (sendStr(socket, "HTTP/1.1 500 Error\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n") == -1) {
close(socket);
}
}
else if (sendStr(socket, "HTTP/1.1 200 OK\r\nContent-Length: " + std::to_string(length) + "\r\nConnection: keep-alive\r\nContent-Type: image/png\r\n\r\n") == -1)
{
close(socket);
}
else if (length > 0)
{
char data[1024];
do
{
if (!in.read(data, std::min(length, sizeof(data))))
{
close (socket);
break;
}
int bytes = in.gcount();
if (sendData(socket, data, bytes) == -1)
{
close(socket);
break;
}
length -= bytes;
}
while (length > 0);
}
}
}
的内容。< / p>
尝试更像这样的东西:
[]