您的位置:首页 > 娱乐 > 明星 > 长春网络公司营销模式_网站认证方式_危机舆情公关公司_百度的seo关键词优化怎么弄

长春网络公司营销模式_网站认证方式_危机舆情公关公司_百度的seo关键词优化怎么弄

2025/8/2 11:48:01 来源:https://blog.csdn.net/2201_75584283/article/details/143251753  浏览:    关键词:长春网络公司营销模式_网站认证方式_危机舆情公关公司_百度的seo关键词优化怎么弄
长春网络公司营销模式_网站认证方式_危机舆情公关公司_百度的seo关键词优化怎么弄

✨个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】【Linux系统编程】【Linux网络编程】

目录

1、HttpRequest类

1.1、基本结构

1.2、构造析构函数

1.3、反序列化函数

1.4、GetLine() 

1.5、打印函数

2、HttpServer类

2.1、HandlerHttpRequest()

3、测试 

3.1、测试结果(基本版本) 

3.2、代码优化一

3.3、测试结果(优化一) 

3.4、代码优化二

3.5、测试结果(优化二) 

4、增加路径字段

4.1、HttpRequest类 

4.2、解析请求行

4.3、获取url 和 path

4.4、HandlerHttpRequest()


1、HttpRequest类

1.1、基本结构

HttpRequest类基本结构包括请求行,请求报头,正文

class HttpRequest
{
private:// \r\n// \r\ndata// 获取一行信息std::string GetLine(std::string &reqstr);// 解析请求行void ParseReqLine();// 解析请求报头,以冒号加空格分隔void ParseReqHeader();
public:HttpRequest();// 反序列化void Deserialize(std::string &reqstr) ;// 打印请求信息void Print();~HttpRequest();
private:// 基本的httprequest的格式std::string _req_line;                 // 请求行std::vector<std::string> _req_headers; // 请求报头std::string _blank_line;               // 空行std::string _body_text;                // 正文
};

1.2、构造析构函数

构造函数初始化空行即可,因为空行是固定的,析构函数无需处理!

const static std::string base_sep = "\r\n";HttpRequest() : _blank_line(base_sep)
{}~HttpRequest()
{}

1.3、反序列化函数

反序列化即将字符串转化成结构化字段

// 反序列化
void Deserialize(std::string &reqstr) 
{// 基本的反序列化_req_line = GetLine(reqstr); // 读取一行,请求行// 请求报头std::string header;do{header = GetLine(reqstr);if (header.empty())break;else if (header == base_sep)break;_req_headers.push_back(header);} while (true);// 正文if (!reqstr.empty()){_body_text = reqstr;}
}

1.4、GetLine() 

获取一行有效信息没找到分隔符返回空串,找到分隔符但是没有有效信息则返回分隔符

// \r\n
// \r\ndata
// 获取一行信息
std::string GetLine(std::string &reqstr)
{auto pos = reqstr.find(base_sep);if (pos == std::string::npos) // 没找到分隔符返回空return std::string();std::string line = reqstr.substr(0, pos);       // 截取一行有效信息reqstr.erase(0, line.size() + base_sep.size()); // 删除有效信息和分隔符return line.empty() ? base_sep : line;          // 有效信息为空则返回分隔符,不为空返回有效信息
}

1.5、打印函数

打印反序列化出来的字符串

// 打印请求信息
void Print()
{std::cout << "---------------------------" << std::endl;std::cout << "###" << _req_line << std::endl;for (auto &header : _req_headers){std::cout << "@@@" << header << std::endl;}std::cout << "***" << _blank_line;std::cout << ">>>" << _body_text << std::endl;
}

2、HttpServer类

2.1、HandlerHttpRequest()

std::string HandlerHttpRequest(std::string &reqstr)
{
#ifdef TESTstd::cout << "---------------------------------------------" << std::endl;std::cout << reqstr;// return std::string();std::string responsestr = "HTTP/1.1 200 OK\r\n";responsestr += "Content-Type: text/html\r\n";responsestr += "\r\n";responsestr += "<html><h1>hello linux,hello net!<h2></html>";return responsestr;
#elseHttpRequest req;         // 构建请求对象req.Deserialize(reqstr); // 反序列化字符串req.Print();             // 打印反序列的字符串return std::string();    // 保证编译通过
#endif
}

3、测试 

主函数

// ./httpserver 8888
int main(int argc, char *argv[])
{if (argc != 2){std::cerr << "Usage: " << argv[0] << "local-port" << std::endl;exit(0);}uint16_t port = std::stoi(argv[1]);HttpServer hserver;std::unique_ptr<TcpServer> tsvr = std::make_unique<TcpServer>(std::bind(&HttpServer::HandlerHttpRequest, &hserver, std::placeholders::_1),port);tsvr->Loop();return 0;
}

3.1、测试结果(基本版本) 

注意:执行的方法都是HandlerHttpRequest(),且代码执行的是#else后的代码!

运行结果 

上面是基本的序列化,我们还可以进一步序列化,将请求行的成员都反序列化,因此请求类需要增加成员变量

3.2、代码优化一

HttpRequest类成员变量

HttpRequest类需要增加请求方法,统一资源定位符,版本三个成员变量

class HttpRequest
{
private:// 基本的httprequest的格式std::string _req_line;                 // 请求行std::vector<std::string> _req_headers; // 请求报头std::string _blank_line;               // 空行std::string _body_text;                // 正文// 更具体的属性字段,需要进一步反序列化std::string _method;  // 请求方法std::string _url;     // 统一资源定位符std::string _version; // 版本
};

反序列化函数

反序列化函数需要增加解析请求行函数

// 反序列化
void Deserialize(std::string &reqstr)
{// 基本的反序列化_req_line = GetLine(reqstr); // 读取一行,请求行// 请求报头std::string header;do{header = GetLine(reqstr);if (header.empty())break;else if (header == base_sep)break;_req_headers.push_back(header);} while (true);// 正文if (!reqstr.empty()){_body_text = reqstr;}// 再进一步反序列化ParseReqLine();   // 解析请求行
}

解析请求行函数

请求行的成员之间使用空格分隔,因此可以使用字符串流对象,直接进行流提取

// 解析请求行
void ParseReqLine()
{std::stringstream ss(_req_line);   // 以空格为分隔符 cin >>ss >> _method >> _url >> _version; // 以空格为分隔符依次将请求行的内容赋值给成员变量
}

打印请求信息

// 打印请求信息
void Print()
{std::cout << "---------------------------" << std::endl;std::cout << "###" << _req_line << std::endl;for (auto &header : _req_headers){std::cout << "@@@" << header << std::endl;}std::cout << "***" << _blank_line;std::cout << ">>>" << _body_text << std::endl;std::cout << "Method: " << _method << std::endl;std::cout << "Url: " << _url << std::endl;std::cout << "Version: " << _version << std::endl;
}

3.3、测试结果(优化一) 

浏览器输入 42.193.244.117:8888

注意:IP是自己服务器的公网IP,并且需要启动可执行程序! 

运行结果

浏览器输入 42.193.244.117:8888/a/b/c/d/e/f/html

运行结果

上面将请求行的成员都反序列化我们还可以进一步序列化,将请求报头进行反序列化,照样需要增加成员变量,此处我们使用哈希表存储,因为每行报文都是以冒号+空格分隔的值

3.4、代码优化二

HttpRequest类成员变量 

HttpRequest类增加一个KV形式的哈希表即可!

class HttpRequest
{
private:// 基本的httprequest的格式std::string _req_line;                 // 请求行std::vector<std::string> _req_headers; // 请求报头std::string _blank_line;               // 空行std::string _body_text;                // 正文// 更具体的属性字段,需要进一步反序列化std::string _method;  // 请求方法std::string _url;     // 统一资源定位符std::string _version; // 版本std::unordered_map<std::string, std::string> _headers_kv; // 存储每行报文的哈希表
};

反序列化函数 

该反序列函数需要加前面的基础上继续解析请求报头

// 反序列化
void Deserialize(std::string &reqstr)
{// 基本的反序列化_req_line = GetLine(reqstr); // 读取一行,请求行// 请求报头std::string header;do{header = GetLine(reqstr);if (header.empty())break;else if (header == base_sep)break;_req_headers.push_back(header);} while (true);// 正文if (!reqstr.empty()){_body_text = reqstr;}// 再进一步反序列化ParseReqLine();   // 解析请求行ParseReqHeader(); // 解析请求报头
}

解析请求报头函数

遍历请求报头成员变量,以行分隔符查找有效信息找到且分隔符前的有效信息不为空且分隔符后的有效信息不为空,则将KV值插入到哈希表中

const static std::string line_sep = ": "; // 行分隔符// 解析请求报头,以冒号加空格分隔
void ParseReqHeader()
{for (auto &header : _req_headers){auto pos = header.find(line_sep);if (pos == std::string::npos)continue;std::string k = header.substr(0, pos);                // 截取key值std::string v = header.substr(pos + line_sep.size()); // 截取value值if (k.empty() || v.empty())continue;_headers_kv.insert(std::make_pair(k, v)); // 将对应的kv值插入到哈希表中}
}

打印请求信息函数

// 打印请求信息
void Print()
{std::cout << "---------------------------" << std::endl;std::cout << "###" << _req_line << std::endl;for (auto &header : _req_headers){std::cout << "@@@" << header << std::endl;}std::cout << "***" << _blank_line;std::cout << ">>>" << _body_text << std::endl;std::cout << "Method: " << _method << std::endl;std::cout << "Url: " << _url << std::endl;std::cout << "Version: " << _version << std::endl;for (auto head_kv : _headers_kv){std::cout << ")))" << head_kv.first << "->"<< head_kv.second << std::endl;}
}

3.5、测试结果(优化二) 

注意:执行的方法都是HandlerHttpRequest(),且代码执行的是#else后的代码!

运行结果 

4、增加路径字段

我们向服务器请求的时候,需要知道资源的路径,因此我们可以增加路径字段(根目录为wwwroot/),当url为 / 时,默认访问wwwroot/index.html

4.1、HttpRequest类 

HttpRequest类增加路径成员,并将路径初始化为web根目录

const static std::string prefixpath = "wwwroot"; // web根目录class HttpRequest
{
public:HttpRequest() : _blank_line(base_sep), _path(prefixpath){}
private:// 基本的httprequest的格式std::string _req_line;                 // 请求行std::vector<std::string> _req_headers; // 请求报头std::string _blank_line;               // 空行std::string _body_text;                // 正文// 更具体的属性字段,需要进一步反序列化std::string _method; // 请求方法std::string _url;    // 统一资源定位符std::string _path;   // 资源路径std::string _version;                                     // 版本std::unordered_map<std::string, std::string> _headers_kv; // 存储每行报文的哈希表
};

4.2、解析请求行

解析请求行除了解析url之外还需要解析path,path 默认直接使用path + url即可,但是当url 为 / 时,path 还需要加上默认访问文件 index.html

// 解析请求行
void ParseReqLine()
{std::stringstream ss(_req_line);   // 以空格为分隔符 cin >>ss >> _method >> _url >> _version; // 以空格为分隔符依次将请求行的内容赋值给成员变量_path += _url;// 只有web根目录返回index.htmlif (_path[_path.size() - 1] == '/'){_path += homepage;}
}

4.3、获取url 和 path

获取url 和 path 直接返回成员变量即可!

std::string Url()
{LOG(DEBUG, "Client Want url %s\n", _url.c_str());return _url;
}
std::string Path()
{LOG(DEBUG, "Client Want path %s\n", _path.c_str());return _path;
}

4.4、HandlerHttpRequest()

std::string HandlerHttpRequest(std::string &reqstr)
{HttpRequest req;         // 构建请求对象req.Deserialize(reqstr); // 反序列化字符串std::string url = req.Url();std::string path = req.Path();return std::string();    // 保证编译通过
}

运行结果 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com