C ++通过HTTP发送PNG文件

时间:2017-04-28 02:03:40

标签: c++ http server

我正在尝试创建一个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);

服务器应该发送图像后,它会显示为丢失的图像图标。

我已经检查过以确保正在发送所有字节,并且正在加载图像。 非常感谢任何帮助!

1 个答案:

答案 0 :(得分:0)

您的代码中存在相当多的错误。

  1. 如果is_open()返回false,您仍在尝试处理该文件。

  2. 当您需要使用\n\r时,您正在使用\r\n

  3. 您正在使用strcat()data追加allData。当附加二进制数据(如PNG)时,strcat()将在遇到的第一个0x00字节上截断。您需要使用memcpy()(或等效的)。

  4. send()发送data时,allData的来电正在发送data。因此,您根本不发送HTTP标头,而是使用错误的长度发送send()

  5. 您假设send()将在一次操作中发送您提供的所有数据。几乎从来没有这种情况,尤其是大量数据。 allData返回它实际接受发送的字节数,因此您需要在循环中调用它,直到所有数据都被接受为止。

  6. 如果在准备文件时出现问题,您不会向客户端发送错误消息。

  7. 话虽如此,headers实际上是不必要的,浪费了记忆。 TCP是一个字节流,因此您可以依次单独发送datasend()。您拨打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>

    尝试更像这样的东西:

    []