解析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来解决问题。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
DBC文件是一种用于描述CAN网络通信协议的文件格式。以下是使用C++解析DBC文件的基本步骤: 1. 打开DBC文件,并读取文件头部信息,包括版本号、节点数和消息数等。 2. 解析节点信息,包括节点名称、节点ID和节点描述等。 3. 解析消息信息,包括消息ID、消息名称、发送节点、接收节点、消息长度和信号数等。 4. 解析信号信息,包括信号名称、起始位、长度、因子、偏移量、最小值、最大值、单位和描述等。 5. 将解析的节点、消息和信号信息存储在内存中,以便后续使用。 以下是一个简单的代码示例,用于读取DBC文件的版本号和节点数: ```cpp #include <iostream> #include <fstream> #include <string> using namespace std; struct DbcHeader { string version; int nodeCount; }; int main() { ifstream dbcFile("test.dbc", ios::binary); if (!dbcFile.is_open()) { cout << "Failed to open DBC file" << endl; return 1; } // Read DBC file header DbcHeader header; dbcFile.seekg(0); dbcFile.read(reinterpret_cast<char*>(&header), sizeof(header)); cout << "DBC version: " << header.version << endl; cout << "Node count: " << header.nodeCount << endl; return 0; } ``` 该示例使用结构体`DbcHeader`来存储DBC文件的头部信息,包括版本号和节点数。然后,通过`ifstream`类打开`test.dbc`文件,并使用`read`函数从文件中读取`DbcHeader`对象的内容。最后,将读取到的版本号和节点数输出到控制台上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qianbo_insist

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值