解析http头部和c++string的高级使用技巧
Posted qianbo_insist
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解析http头部和c++string的高级使用技巧相关的知识,希望对你有一定的参考价值。
需求
需求是解析upnp协议中的http 协议 和xml 中取得响应的内容,使用c++字符串的高级特性和http协议“\\r\\n”的特性匹配,使用std::istringstream来获取string 类中的每一行,分而治之,对每一行字符串再进行分解,达到我们解析头部的目的,事实上,没有完美无缺的技术,各个协议都是用的组合拳,把各类协议组合而得到一个完整的解决方案,upnp协议就是组播协议套上使用http 和 xml 以及soap 等来完成发现和控制。
http协议头部示例
HTTP/1.1 200 OK
CACHE-CONTROL: max-age=300
DATE: Sat, 19 Jun 2021 08:10:55 GMT
EXT:
LOCATION: http://192.168.0.104:25826/description.xml
OPT: “http://schemas.upnp.org/upnp/1/0/”; ns=0101-NLS: 1d14711e-d0b3-11eb-ba82-84a8e6833d02
SERVER: Linux/4.9.44_s5, UPnP/1.0, Portable SDK for UPnP devices/1.6.19
X-User-Agent: redsonic
ST: urn:schemas-upnp-org:device:MediaRenderer:1
USN: uuid:bb5e-21ce-1111-11b2-f918-ec9c-3235-709a-::urn:schemas-upnp-org:device:MediaRenderer:1
我们需要拿到http 的版本和返回状态如 200 和 reason like “ok”
同时解析里面的每条内容,拿到每个header 的头部 行成 map<string,string>的结构返回
定义数据结构
typedef struct s_res
{
string httpver;
int status;
string reason;
}s_res;
事实上,对于以下
//GET /live/1001 HTTP/1.1
//HTTP/1.1 200 OK
//POST /live/1001 HTTP/1.1
等我们都可以使用这种方法
下面开始解析,流程是
1 解析是否有HTTP 头部四字节
2 如果有,拿到HTTP头部后的返回状态status 和 reason
3 解析剩下的每一行,每一行都是 x :y 的结构,放入map
static s_res fetch_head_info(std::string &lines, map<string,string> &hmap)
{
s_res res = {"",-1,""};
if (strncmp(lines.c_str(), "HTTP", 4) != 0)
{
//not support now
return res;
}
std::istringstream s(lines);
std::string request;
std::getline(s, request);
if (request[request.size() - 1] == '\\r')
{
request.pop_back();
//request.erase(request.end() - 1);//the same with pop_back
//GET /live/1001 HTTP/1.1
//HTTP/1.1 200 OK
size_t i = 5;
size_t lmax = request.size();
while (request[++i] != ' ' && i < lmax);
if (i == lmax - 1)
return res;
res.httpver = request.substr(5, i - 5);
size_t pos = ++i;
while (request[i++] != ' ' && i < lmax);
if (i == lmax - 1)
return res;
string s = request.substr(pos, i - pos);
res.status = atoi(s.c_str());
res.reason = request.substr(i, lmax - i);
}
else
return res;
hmap.clear();
std::string header;
std::string::size_type end;
2 步开始
while (std::getline(s, header) && header != "\\r")
{
if (header[header.size() - 1] == '\\r')
{
//header.pop_back(); //or use this function
header.erase(header.end() - 1); //remove last char
end = header.find(": ", 0);
if (end != std::string::npos)
{
std::string key = header.substr(0, end);
std::string value = header.substr(end + 2);
hmap[key] = value;
}
}
}
return res;
}
这样我们有效快速使用c++ string 的高级特性获取http协议的每一行,使用方法:
map<string, string> ss;
s_res res = fetch_head_info(sdata, ss);
if (res.status == 200)
{
string lo = ss["LOCATION"];
//const char *url = "http://192.168.1.144:1551/AVTransport/cff47b40-2475-7ff1-7459-318ec45c9853/control.xml";
const char *pos = lo.c_str();
char http[256] = {"http://" };
......
}
其中我们的res.status == 200 代表http协议返回正常,否则我们另作处理, 也可以加上判断结构体中的reason为"OK"
接下来一篇,我们将介绍如何解析upnp协议中的xml ,而不引入更多的库,使用c语言的strstr和sscanf来解决问题。
以上是关于解析http头部和c++string的高级使用技巧的主要内容,如果未能解决你的问题,请参考以下文章