基于多反应堆的高并发服务器【C/C++/Reactor】(中)HtttpRequest的定义和初始化、资源重置和销毁

发布时间:2024年01月08日

一、Get方式提交数据

如果使用get的方式向服务器提交数据,数据并没有在请求协议的第四部分,而是在请求行的第二部分。如果使用get方式提交数据,第四部分是空的

这是浏览器对用户的请求数据进行了封装之后,得到的原始的http请求数据

>>http get请求报文的格式
请求行\r\n
请求头\r\n
空行(\r\n)
 
提示: 每项信息之间都需要一个\r\n,是由http协议规定
 
************************************************
************************************************
>>http post请求报文的格式
请求行\r\n
请求头\r\n
空行(\r\n)
请求体
 
提示: 请求体就是浏览器发送给服务器的数据

在HTTP报文中,每一行的数据有\r\n作为结束字符,空行则是仅仅是字符\r\n。因此,可以通过查找\r\n将报文拆解成单独的行进行解析,项目中便是利用了这一点。?

?(一)HtttpRequest的定义

// 请求头键值对
struct RequestHeader{
    char* key;
    char* value;
};

// 当前的解析状态
enum HttpRequestState {
    ParseReqLine,    // 当前解析的是请求行
    ParseReqHeaders, // 当前解析的是请求头
    ParseReqBody,    // 当前解析的是请求体
    ParseReqDone     // 完成解析
};

// 定义 http 请求结构体
struct HttpRequest {
    // 当前解析状态
    enum HttpRequestState curState;  
    // 请求行
    char* method;
    char* url;
    char* version;  
    // 请求头
    struct RequestHeader* reqHeaders;
    int reqHeadersNum;
};

(二)初始化

// 初始化
struct HttpRequest* httpRequestInit();
struct HttpRequest* httpRequestInit() {
    struct HttpRequest* request = (struct HttpRequest*)malloc(sizeof(struct HttpRequest));
    request->curState = ParseReqLine;
    // 请求行
    request->method = NULL;
    request->url = NULL;
    request->version = NULL;
    // 请求头
    request->reqHeaders = (struct RequestHeader*)malloc(sizeof(struct RequestHeader) * HeaderSize);
    request->reqHeadersNum = 0;
    return request;
}

(三)初始化、资源重置

资源重置:当一个浏览器和服务器建立连接之后,浏览器给服务器发送数据,服务器接收到浏览器的请求消息之后,就需要进行解析了。解析之后的数据存储到HttpRequest结构体里边,对于method,url,version它们是指针,其实是需要指向一块有效的内存的。再给这个指针赋值的时候,需要先malloc一块内存,再让指针指向这块内存。如果这个浏览器和服务器建立连接之后,它们进行了多次通信,那么就需要多次往HttpRequest结构体里边写数据,第一次写的时候,method对应一块堆内存。那么再次写入,需要把上次写入的数据清除掉,由于清除的是堆内存,可以用free函数?(防止内存泄漏)

// 初始化
struct HttpRequest* httpRequestInit();

// 重置
void httpRequestReset(struct HttpRequest* req);
void httpRequestResetEx(struct HttpRequest* req);
// 初始化
struct HttpRequest* httpRequestInit() {
    struct HttpRequest* request = (struct HttpRequest*)malloc(sizeof(struct HttpRequest));
    httpRequestReset(request);
    request->reqHeaders = (struct RequestHeader*)malloc(sizeof(struct RequestHeader) * HeaderSize);
    return request;
}

// 重置
void httpRequestReset(struct HttpRequest* req) {
    req->curState = ParseReqLine;
    req->method = NULL;
    req->url = NULL;
    req->version = NULL;
    req->reqHeadersNum = 0;
}

void httpRequestResetEx(struct HttpRequest* req) {
    free(req->method);
    free(req->url);
    free(req->version);
    if(req->reqHeaders != NULL) {
        for(int i=0;i<req->reqHeadersNum;++i) {
            free(req->reqHeaders[i].key);
            free(req->reqHeaders[i].value);
        }
        free(req->reqHeaders);
    }
    httpRequestReset(req);
}

(四)销毁

// 销毁
void httpRequestDestroy(struct HttpRequest* req);
void httpRequestDestroy(struct HttpRequest* req) {
    if(req != NULL) {
        httpRequestResetEx(req);
        free(req);
    }
}

(五)学习笔记

一、关于指针与内存

  1. 在给指针赋值之前,需要先分配一块有效的内存
  2. 当浏览器客户端与服务器建立连接并进行多次通信时,需要多次向HttpRequest结构体中写入数据
  3. 如果需要重置HttpRequest结构体,只需重置指针指向的内存中的数据,而不需要销毁整个结构体的内存地址
  4. 当重置指针时,如果之前没有释放对应的内存,会导致内存泄漏

二、关于释放内存

  • 在释放内存时,应先释放结构体成员中的指针所指向的内存
  • 对于指向请求行数据的url、method和version,可以直接调用HTTP请求重置函数进行释放
  • 对于结构体中的reqHeaders指针指向的内存,需要先判断指针是否为空,再释放对应的内存

三、注意事项

  1. 在使用指针之前,确保为其分配了有效的内存
  2. 在重置或释放内存后,确保指针指向正确的位置或设置为空
  3. 避免内存泄漏,确保在适当的时候释放已分配的内存
文章来源:https://blog.csdn.net/weixin_41987016/article/details/135460755
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。