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

一、HttpResponse的定义

1.定义状态码枚举

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

2.HTTP 响应报文格式

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

  1. 第一部分是状态行
  2. 第二部分是响应头
  3. 第三部分是一个空行
  4. 第四部分是给客户端回复的数据块
cpp 复制代码
// 定义响应的结构体
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...需要根据客户端的请求去回复相应的数据。所以如何去组织这个需要回复的数据块呢?

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

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

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

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

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

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

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

二、HttpResponse的初始化

cpp 复制代码
// 初始化
struct HttpResponse* httpResponseInit();
cpp 复制代码
#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的销毁 内存释放

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

四、添加响应头

cpp 复制代码
// 添加响应头
void httpResponseAddHeader(struct HttpResponse* response,const char* key,const char* value);
cpp 复制代码
// 添加响应头
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响应数据

cpp 复制代码
// 组织http响应数据
void httpResponsePrepareMsg(struct HttpResponse* response,struct Buffer* sendBuf,int socket);
cpp 复制代码
// 组织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;i<response->headerNum;++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);
}
相关推荐
呵呵哒( ̄▽ ̄)"10 个月前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)HttpRequest模块 解析http请求协议
基于多反应堆的·高并发服务器·c/c++/reactor
_snowstorm_10 个月前
Linux学习之网络编程3(高并发服务器)
linux·服务器·学习·高并发服务器·多进程高并发服务器·多线程高并发服务器
呵呵哒( ̄▽ ̄)"10 个月前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)完整代码
高并发服务器·c/c++/reactor·多反应堆
呵呵哒( ̄▽ ̄)"10 个月前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)HttpRequest 提取请求行、解析请求行和优化 以及解析请求头并存储
请求行·请求头·基于多反应堆的·高并发服务器·c/c++/reactor
呵呵哒( ̄▽ ̄)"10 个月前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)创建一个TcpConnection实例 以及 接收客户端数据
基于多反应堆的·高并发服务器·c/c++/reactor
呵呵哒( ̄▽ ̄)"10 个月前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)处理任务队列中的任务
删除·基于多反应堆的·高并发服务器·c/c++/reactor·处理任务队列中的任务·添加·修改
呵呵哒( ̄▽ ̄)"10 个月前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)主线程给子线程添加任务以及如何处理该任务
基于多反应堆的·高并发服务器·c/c++/reactor
呵呵哒( ̄▽ ̄)"10 个月前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)子线程 WorkerThread的实现 和 线程池ThreadPool的初始化
高并发服务器·c/c++/reactor·多反应堆·workerthread的实现
呵呵哒( ̄▽ ̄)"10 个月前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)在EventLoop中处理被激活的文件描述符的事件
eventloop·高并发服务器·c/c++/reactor·多反应堆·处理被激活的文件描述符的事件