所以我需要编写一个 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
如有帮助,我们将不胜感激。谢谢🙂
对于将来遇到这个问题的人来说。感谢 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 函数仅适用于较小的缓冲区大小。如果您想要更大的缓冲区大小,则必须检查第一次迭代。我知道它写得不太清楚,但它只是一个原型。