C++ C++;通过HTTP发送PNG文件

C++ C++;通过HTTP发送PNG文件,c++,http,server,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:

我正在尝试创建一个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);
std::ifstream-in(“P:/server”+位置,std::ios::binary);
如果(!in.is_open()){

std::cout您的代码中有很多错误

  • 如果
    is\u open()
    返回false,您仍在尝试处理该文件

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

  • 您正在使用
    strcat()
    数据
    附加到
    所有数据
    。当附加二进制数据(如PNG)时,
    strcat()
    将截断遇到的第一个
    0x00
    字节。您需要改用
    memcpy()
    (或等效物)

  • 您对
    send()
    的调用正在发送
    data
    ,而此时它应该发送
    allData
    。因此,您根本没有发送HTTP头,而是使用错误的长度发送
    data

  • 您假设
    send()
    将在一次操作中发送您提供给它的所有数据。这几乎不是事实,尤其是对于大量数据。
    send()
    返回它实际接受发送的字节数,因此您需要在一个循环中调用它,直到所有数据都被接受

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

  • 也就是说,
    allData
    实际上是不必要的,而且是一种内存浪费。TCP是一个字节流,因此您可以逐个发送
    headers
    data
    。调用
    send()
    的次数不会影响另一方接收数据的方式

    您还可以考虑通过将<代码>数据< /代码>更改为固定大小的缓冲区,从而在<>代码> > <代码> > <>代码> >

    。 请尝试类似以下内容:

    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);
            }
        }
    }
    
    int-sendData(int-sckt、const-void*data、int-datalen)
    {
    const char*ptr=静态_cast(数据);
    而(数据长度>0){
    int字节=发送(sckt、ptr、datalen、0);
    
    if(bytes)寻求调试帮助的问题(“为什么此代码不工作?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现该问题所需的最短代码请随您观察到的任何问题一起发布。HTTP标准调用
    \r\n
    而不是
    \n\r
    。strcat?真的吗?PNG不是字符串。至少有两个。谢谢,这肯定是问题所在!