一、HttpResponse的定义
1.定义状态码枚举
// 定义状态码枚举
enum HttpStatusCode {Unknown = 0,OK = 200,MovedPermanently = 301,MovedTemporarily = 302,BadRequest = 400,NotFound = 404
};
2.HTTP 响应报文格式
这个数据块主要是分为四部分
- 第一部分是状态行
- 第二部分是响应头
- 第三部分是一个空行
- 第四部分是给客户端回复的数据块
// 定义响应的结构体
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;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);
}