基于多反应堆的高并发服务器【C/C++/Reactor】(中)HttpResponse的定义和初始化 以及组织 HttpResponse 响应消息

一、HttpResponse的定义

1.定义状态码枚举

// 定义状态码枚举
enum HttpStatusCode {
    Unknown = 0,
    OK = 200,
    MovedPermanently = 301,
    MovedTemporarily = 302,
    BadRequest = 400,
    NotFound = 404
};

2.HTTP 响应报文格式

基于多反应堆的高并发服务器【C/C++/Reactor】(中)HttpResponse的定义和初始化 以及组织 HttpResponse 响应消息_第1张图片

 这个数据块主要是分为四部分

  1. 第一部分是状态行
  2. 第二部分是响应头
  3. 第三部分是一个空行
  4. 第四部分是给客户端回复的数据块
// 定义响应的结构体
struct ResponseHeader {
    char key[32];
    char value[128];
};

// 定义一个函数指针,用来组织要回复给客户端的数据块
typedef void (*responseBody) (const char* fileName,struct Buffer* sendBuf,int socket);

// 定义结构体
struct HttpResponse {
    // 状态行:状态码,状态描述
    enum HttpStatusCode statusCode;
    char statusMsg[128];
    // 响应头 - 键值对
    struct ResponseHeader* headers;
    int headerNum;
    responseBody sendDataFunc;
    // 文件名
    char fileName[128];
};

服务器回复给客户端的数据,取决于客户端向服务器请求了什么类型的资源,有可能它请求的是一个目录,有可能请求的是一个文件,这个文件有可能是一个文本文件,也可能是一个图片,还可能是mp3...需要根据客户端的请求去回复相应的数据。所以如何去组织这个需要回复的数据块呢?

// 定义一个函数指针,用来组织要回复给客户端的数据块
typedef void (*responseBody) (const char* fileName,struct Buffer* sendBuf,int socket);

fileName:分成两类,一类是目录类型,类是非目录类型的文件

  • 如果是目录,就去遍历目录
  • 如果是文件,就读取其内容

sendBuf:在进行套接字的通信过程中:

  • 如果要回复数据(给客户端发数据),发送的数据要先存储到sendBuf里边,再发送给客户端.

socket:就是用来通信的文件描述符,通过这个用于通信的文件描述符,就能够把写入到sendBuf里边的数据发送给客户端,sendBuf里边的数据就是我们组织好的Http响应的数据块

  • 定义一个函数指针,用来组织要回复给客户端的数据块
responseBody sendDataFunc;

二、HttpResponse的初始化

// 初始化
struct HttpResponse* httpResponseInit();
#define ResHeaderSize 16
// 初始化
struct HttpResponse* httpResponseInit() {
    struct HttpResponse* response = (struct HttpResponse*)malloc(sizeof(struct HttpResponse));
    // 状态行:状态码,状态描述
    response->statusCode = Unknown;
    bzero(response->statusMsg,sizeof(response->statusMsg));

    // 响应头 - 键值对
    int size = sizeof(struct ResponseHeader) * ResHeaderSize;
    response->headers = (struct ResponseHeader*)malloc(size);
    bzero(response->headers, size);
    response->headerNum = 0;

    // 函数指针
    response->sendDataFunc = NULL;

    // 文件名
    bzero(response->fileName,sizeof(response->fileName));
    return response;
}

三、HttpResponse的销毁 内存释放

// 销毁
void httpResponseDestroy(struct HttpResponse* response);
// 销毁
void httpResponseDestroy(struct HttpResponse* response) {
    if(response!=NULL) {
        free(response->headers);
        free(response);
    }
}

四、添加响应头

// 添加响应头
void httpResponseAddHeader(struct HttpResponse* response,const char* key,const char* value);
// 添加响应头
void httpResponseAddHeader(struct HttpResponse* response,const char* key,const char* value){
    if(response == NULL || key == NULL || value == NULL) {
        return;
    }
    strcpy(response->headers[response->headerNum].key,key);
    strcpy(response->headers[response->headerNum].value,value);
    response->headerNum++;
}

五、组织http响应数据

// 组织http响应数据
void httpResponsePrepareMsg(struct HttpResponse* response,struct Buffer* sendBuf,int socket);
// 组织http响应数据
void httpResponsePrepareMsg(struct HttpResponse* response,struct Buffer* sendBuf,int socket) {
    // 状态行
    char tmp[1024] = {0};
    sprintf(tmp,"HTTP/1.1 %d %s\r\n",response->statusCode,response->statusMsg);
    bufferAppendString(sendBuf,tmp);
    
    // 响应头
    for(int i=0;iheaderNum;++i) {
        // memset(tmp,0,sizeof(tmp));  ?????????
        sprintf(tmp,"%s: %s\r\n",response->headers[i].key,response->headers[i].value);
        bufferAppendString(sendBuf,tmp);
    }

    // 空行
    bufferAppendString(sendBuf,"\r\n");
    // 回复的数据
    response->sendDataFunc(response->fileName,sendBuf,socket);
}

你可能感兴趣的:(高并发服务器,C/C++/Reactor,基于多反应堆的)