我正在尝试用c++构建一个http服务器。因此,在我决定如何提取body实体的条件中,是否存在内容长度?下面是我如何使用Content-Length
提取body
的最小代码:
req_t *Webserver::_recv(int client_fd, bool *closed)
{
string req;
static string rest;
// string extracted_req;
char buff[1024];
// while (true) {
// std::cout << "client_fd: " << client_fd << std::endl;
int n = recv(client_fd, buff, 1024, 0);
// std::cout << "n: " << n << std::endl;
if (n == -1)
{
_set_error_code("500", "Internal Server Error");
return NULL;
}
if (n == 0)
{
*closed = true;
return NULL;
}
buff[n] = '\0';
req += buff;
req_t *extracted_req = _extract_req(client_fd, req, rest, closed);
return extracted_req;
}
...
else if (headers.find("Content-Length") != string::npos) {
string body = extract_body_len(client_fd, rest_of_req, content_length);
}
req_t
是一个简单的结构体,它包含三个字符串status_line
、headers
和body
。
第一次
现在,问题是我已经测试了不同大小的正文实体(8MB,1.9MB,31 MB)的请求,并且一直没有收到整个正文(根据内容长度),模式如下:
recv
继续阅读所有1024字节,直到total
更接近len
,然后它开始读取更小的数字。直到total
和len
之间的差大约为400...600字节,然后recv
在total
==len
之前的某个点处阻塞(没有更多要读取的)。
这真的让我很困惑,我尝试了不同的api客户端(postman,insonomia),但结果相同,我怀疑可能Content-Length
不是那么准确but it obviously should be,你认为问题是什么,为什么我接收或阅读的少于Content-Length
?
1条答案
按热度按时间oyjwcjzk1#
上面的代码似乎假设这个
recv
调用只返回HTTP请求的头部,一个字节也不多,一个字节也不少。不幸的是,你在网络编程的教科书中找不到任何东西能给你任何这样的保证。
您唯一的保证(假设没有套接字级别的错误)是
recv()
将返回一个介于1和1024之间的值,表示套接字上已经接收了多少字节,或者在它阻塞和等待的第一个数据包中到达了多少字节。使用一个完整的HTTP请求示例,如下所示:
当您的Web浏览器或模拟浏览器发送此请求时,此
recv
调用可以返回1到1024之间的任何值(网络错误除外)。这意味着此
recv
调用可以提供以下范围内的任何内容:buff
。所示的逻辑完全不能正确处理所有这些可能性,这就是它失败的原因。它需要重新实现,几乎是从头开始,使用正确的逻辑。