基于多反应堆的高并发服务器【C/C++/Reactor】(中)解析请求头并存储

2024-01-08 20:32:26

一、解析请求头并存储

### 解析请求头数据

1.数据存储在对应的Buffer结构内存块中。解析时,需要将readPos更新到请求头的起始位置parseHttpRequestLine函数中已经为解析请求头做好了准备。

  • 回顾一下parseHttpRequestLine函数:
bool parseHttpRequestLine(struct HttpRequest* request, struct Buffer* readBuf) {
    ...
    if (lineSize>0)
    {
        start = splitRequestLine(start, end, " ", &request->method);
        start = splitRequestLine(start, end, " ", &request->url);
        splitRequestLine(start, end, NULL, &request->version);

        // 为解析请求头做准备
        readBuf->readPos += lineSize;
        readBuf->readPos += 2;
        // 修改状态
        request->curState = ParseReqHeaders;
        return true;
    }
    return false;
}

2.请求头的每行为一对键值对,包含一个key值和一个value

3.将数据行存储到堆内存中,并将堆内存地址传递给httpRequestAddHeader函数

  • 回顾一下httpRequestAddHeader函数:
void httpRequestAddHeader(struct HttpRequest* request, const char* key, const char* value) {
    request->reqHeaders[request->reqHeadersNum].key = (char*)key;
    request->reqHeaders[request->reqHeadersNum].value = (char*)value;
    request->reqHeadersNum++;
}

### 解析请求头数据 该函数处理请求头中的一行

?

  1. 标准HTTP协议中,键值和值之间使用冒号分隔,冒号后有一个空格
  2. 使用memem函数检查中间指针是否指向冒号
// 解析请求头
bool parseHttpRequestHeader(struct HttpRequest* req,struct Buffer* readBuf);
// 该函数处理请求头中的一行
bool parseHttpRequestHeader(struct HttpRequest* req,struct Buffer* readBuf) {
    char* end = bufferFindCRLF(readBuf);
    if(end!=NULL) {
        char* start = readBuf->data + readBuf->readPos;
        int lineSize = end - start;
        // 基于: 搜索字符串
        char* middle = memmem(start,lineSize,": ",2);    
        if(middle!=NULL) {
            // 拿出键值对
            char* key = malloc(middle - start + 1);
            strncpy(key,start,middle - start);
            key[middle - start] = '\0';// 获得key
            
            char* value = malloc(end - middle - 2 + 1);// end-(middle+2) + 1 = end - middle - 2 + 1
            strncpy(value,middle+2,end - middle - 2);
            value[end - middle - 2] = '\0';// 获得value

            httpRequestAddHeader(req,key,value);// 添加键值对
            // 移动读数据的位置
            readBuf->readPos += lineSize;
            readBuf->readPos += 2;
        }
        else {
            // 请求头被解析完了,跳过空行
            readBuf->readPos += 2;
            // 修改解析状态
            // 本项目忽略 post 请求,按照 get 请求处理
            req->curState = ParseReqDone;
        }
        return true;
    }
    return false;
}

?## 注意事项

总结提取请求行 和 解析请求行和优化?这篇博客和 本文需要注意的细节如下:

  1. 在解析请求行和头部时,需要提供相应的解析函数
  2. 解析函数应返回布尔值,表示解析是否成功
  3. 在读取网络数据时,需要使用封装的bufferSocketRead函数来读取数据
  4. 读取的数据存储在struct Buffer结构体实例中,该实例作为参数传递给解析函数

文章来源:https://blog.csdn.net/weixin_41987016/article/details/135464760
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。