C++98中的HTTP服务器recv/read未收到正确的数据(TCP)

问题描述 投票:0回答:1

所以我需要编写一个 C++ http 1.1 服务器,但我遇到了 read/recv 无法正确获取数据的问题。发生的情况是我没有收到接收二进制文件时所需的一些位。

我得到的输出是

M-^IPNG^M$ ^Z$ IHDR^H^FM-tM-.M-F^DsBIT^H^H^H^H|^HdM-^H^YtEXtSoftwaregnome-screenshotM-o^CM-?>tEXtCreation TimeSat 2024 年 10 月 26 日星期六 07:34:33 CEST^ KuM-8M-:IDAT^HM-^YcM-|M-^?M-^?M-^?^?^F$M-@M-DM-^@^F0^D$ ^D^BM-FuV4ENDM-.B`M-^B

但是我应该收到的内容是

M-^IPNG^M$ ^Z$ ^@^@^@^MIHDR^@^@^@^D^@^@^@^C^H^F^@^@^@M-4M-tM-.M-F^@^@^@^DsBIT ^H^H^H^H|^HdM-^H^@^@^@^YtEXtSoftware^@gnome-screenshotM-o^CM-?>^@^@^@.tEXt创建时间^@Sat 26 Oct 2024 07 :34:33 PM CEST^KuM-8M-:^@^@^@^UIDAT^HM-^YcM-|M-^?M-^?M-^?^?^F$M-@M-DM -^@^F0^D^@M-B$ ^D^BM-FuV4^@^@^@^@IENDM-.B`M-^B

此外,当我查看浏览器时,我可以从网络选项卡中看到我收到了应有的内容,但随后recv/read不会读取丢失的字节(如我得到的输出所示)

这是接收内容并将内容发送到 POST/GET/DELETE 请求的代码。请不要评论“你为什么这样写。方法应该......”。我只需要了解为什么 read/recv 没有获取所有字节。还尝试在“char buffer[2]”中使用更高的读取数量。不会改变任何东西。

std::size_t len(char *str) {
    int i = 0;
    while (str[i++]);
    return i;
}

static char *add(char *buffer, char *to_add) {
    char *returning = (char *)malloc(len(buffer) + 3);
    int i = 0;
    while (buffer[i]) {
        returning[i] = buffer[i];
        i++; 
    }
    free(buffer);
    returning[i++] = to_add[0];
    returning[i++] = to_add[1];
    returning[i] = 0;
    return returning;
}

void Webserv::run(int socket) {
    struct sockaddr_in client_addr;
    socklen_t client_len = sizeof(client_addr);
    int response_content = 0;
    char buffer[2];
    int client_socket;
    char *buff;
    std::string request;

    std::cout << "Server is running and waiting for connections on port: " << port << std::endl;
    std::cout << "http://localhost:" << port << "/" << std::endl;

    while (true) {
        std::string boundary;
        int read_status = 1;
        bool loop = false;
        boundary.clear();
        client_socket = accept(socket, (struct sockaddr*)&client_addr, &client_len);
        if (client_socket < 0) {
            std::cerr << "Error accepting connection" << std::endl;
            continue;
        }

        // std::cout << "Connection accepted." << std::endl;
        memset(buffer, 0, sizeof(buffer));
        int temp = 0;
        std::cout << "A" << std::endl;
        buff = (char *)malloc(1);
        buff[0] = 0;
        while (read_status != 0 && read_status != -1) {
            read_status = recv(client_socket, buffer, sizeof(buffer) - 1, 0);
            // std::cout << buffer << std::endl;
            buff = add(buff, buffer);
            request += std::string(buffer);
            if (!body(request, temp, loop, boundary))
                break;
            temp++;
        }
        std::cout << buff << std::endl;
        std::cout << "A" << std::endl;
        // std::cout << request << std::endl;

        if (read_status == 0 || read_status == -1)
            close(client_socket);

        rq = request;
        // std::cout << request << std::endl;
        request.clear();
        int status_code = get_status_code(rq);

        if (rq.get_method() == "GET")
            response_content = GET(status_code, client_socket);
        else if (rq.get_method() == "POST")
            response_content = POST(status_code, client_socket);
        else if (rq.get_method() == "DELETE")
            response_content = DELETE(status_code, client_socket);
        else
            show_page("text/html", "error_pages/406_error_page.html", 406);
        // std::cout << response_content << std::endl;
        // request.clear();
        close(client_socket);
    }
}

无论我将它与 C 函数和 char* 还是与 std::string 一起使用,字符都丢失了。我没有尝试过的是 std::vector

如有帮助,我们将不胜感激。谢谢🙂

c++ http websocket
1个回答
0
投票

对于将来遇到这个问题的人来说。感谢 Barmar 我可以解决这个问题。如果你想没有错误地阅读,我用这个

int read() {
    std::vector<uint8_t> vector;
    int temp = 0;
    int read_status = 1;
    
    memset(buffer, 0, sizeof(buffer));
    while (true) {
        read_status = recv(client_socket, buffer, sizeof(buffer) - 1, 0);
        if (read_status == 0 || read_status == -1)
            break;
        for (int i = 0; i < read_status; i++)
            vector.push_back(buffer[i]);
        for (std::vector<uint8_t>::iterator it = vector.begin(); it != vector.end(); ++it)
            request += *it;
        vector.clear();
        if (!body(request, temp, loop, boundary))
            break;
        temp++;
    }
}

bool body(std::string request, int temp, bool &loop, std::string& boundary) {
    bool found = false;

    if (temp == 0) {
        return true;
    }
    std::stringstream stream(request);
    std::string line;
    if (!loop) {
        while (std::getline(stream, line)) {
            if (line.find("boundary=") != std::string::npos) {
                std::size_t pos = line.find("boundary=");
                line.erase(0, pos + 9);
                boundary = "--" + line;
                boundary.erase(boundary.length() - 1, boundary.length());
                if (boundary[boundary.length() + 1] == 10)
                    loop = true;
                stream.clear();
                line.clear();
                break;
            }
        }
    }
    if (request.find(boundary + "--") != std::string::npos) {
        return false;
    }
    if (boundary.length() == 0) {
        if (request.find("\r\n\r\n") != std::string::npos) {
            return false;
        }
    }
    return true;
}

body 函数仅适用于较小的缓冲区大小。如果您想要更大的缓冲区大小,则必须检查第一次迭代。我知道它写得不太清楚,但它只是一个原型。

© www.soinside.com 2019 - 2024. All rights reserved.