一、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);
}
}
(五)学习笔记
一、关于指针与内存
二、关于释放内存
三、注意事项