您当前的位置: 首页 > 

qianbo_insist

暂无认证

  • 0浏览

    0关注

    399博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

c函数strstr和sscanf组合高级技巧

qianbo_insist 发布时间:2021-06-19 17:25:45 ,浏览量:0

需求

上一章我们解析完了upnp协议中的http头部获取了xml文件的地址,使用http协议我们再次获取xml文件后需要解析xml,我们最害怕的就是引入一个又一个库,事实上,libupnp就引入了很多库,造成了程序臃肿,打印频繁,我们使用c语言的strstr和sscanf来手动解析xml,获取特定字符串。

1、分解url

upnp协议中的LOCATION是从http头部获取而来,要知道如何获取,请看这一片文章

解析http头部 接下来就是使用sscanf函数来获取http 的host 端口和路由信息,如 http://192.168.1.144:1551/description.xml 我们要分解成为 http://192.168.1.144:1551/ 和路由 /description,使用一个非常绚丽的技巧,如下所示:

	const char *pos = ss["LOCATION"].c_str();
		//const char *url = "http://192.168.1.144:1551/description.xml";
	char http[256] = {"http://" };
	char route[256] = { 0 };
	if (*(pos + 4) == ':')
	pos += 7;
	sscanf(pos, "%[^/]%s", &http[7],route);

以上先把http://填入缓冲中,然后让sscanf 中缓冲的指针指向第7个字节,开始往里放解析值,sscanf函数跳过http://,找到我们字符串的下一个"/"位置。 ok,我们使用http协议下载xml文件,下载结束,得到xml body

1、下载下来后xml body

我们使用http协议在程序中拿到了xml body体




1
0


uuid:bb5e-21ce-1111-11b2-f918-ec9c-3235-709a-
Living Room 1_5336_HiDMR
urn:schemas-upnp-org:device:MediaRenderer:1
Hisilicon Technologies Co., Ltd
http://www.Hisilicon.com
	Hisilicon MediaRenderer
	1.1
	http://www.Hisilicon.com
	
	DMR-1.50
	
	
	
	urn:schemas-upnp-org:service:ConnectionManager:1
	urn:upnp-org:serviceId:ConnectionManager
	
	//需要获得下面这个controlURL
		/upnp/service/ConnectionManager/Control
	/upnp/service/ConnectionManager/Event
	/upnp/service/cms.xml
	
	
	urn:schemas-upnp-org:service:AVTransport:1
	urn:upnp-org:serviceId:AVTransport
	
	//需要获得下面这个controlURL
	/upnp/service/AVTransport/Control
	/upnp/service/AVTransport/Event
	/upnp/service/avt.xml
	
	
	urn:schemas-upnp-org:service:RenderingControl:1
	urn:upnp-org:serviceId:RenderingControl
	
	//需要获得下面这个controlURL
	/upnp/service/RenderingControl/Control
	/upnp/service/RenderingControl/Event
	/upnp/service/rcs.xml< / SCPDURL>
	
	
	
	

这是一份upnp协议中的设备xml 描述,里面包含了几个关键信息,需要我们获取 我们需要的是:

1 设备名称 2 AVTransport 传输点的控制url 3 RenderingControl 点的控制url

熟悉upnp协议的同志们知道这个非常关键,下面我们来制定解决方案

2、定义数据结构
typedef struct s_xmlanalyse_c
{
	char friendlyName[64];
	char url_AVTransport[256];
	char url_RenderingControl[256];
	char url_ConnectionManager[256];
}s_xmlanalyse_c;

定义得到单个节点的内容函数,使用strstr函数来得到xml 字符串中的位置,将字符串内容使用memcpy来复制,字符串的本质是可打印并且最后一个字符是’\0’,因此我们使用memcpy 和 '\0’来生成新的字符串。


const char *GetValueOf_c(const char *sbody, const char *name, char *ret,int retlen)
{
	if (strlen(name) > 63)
		return NULL;
	char buf_fn1[64];
	char buf_fn2[64];
	sprintf(buf_fn1, "", name);
	sprintf(buf_fn2, "", name);
	const char *start = sbody;
	const char *end = sbody + strlen(sbody);

	char *fn =  &buf_fn1[0];
	char *fnn = &buf_fn2[0];
	int len = strlen(fn);
	const char * x1 = strstr(start, fn);
	const char * x2 = strstr(start + len,fnn);
	if (x1 != NULL && x2 != NULL)
	{
		x1 += len;
		int len2 = (int)(x2 - x1);
		if (len2 > retlen - 1)
			return NULL;
		memcpy(ret, x1, x2 - x1);
		ret[x2 - x1] = '\0';
		return x2 + len+1;
	}
	return NULL;
}
获取三个节点内容

使用三个循环获取内容


int GetValueOf_Service_c(const char *fpos, s_xmlanalyse_c *value)
{
	const char * fname  = "serviceType";
	const char * fname2 = "controlURL";
	int flag = 0;
	char tmp[256];
	for (int i = 0; i url_RenderingControl,sizeof(value->url_RenderingControl));
			flag++;
		}
	}
	if (flag == 3)
		return 0;
	return -1;
}
总结

我们使用分解分而治之对待软件工程的方式,首先 A 定义数据结构 B 得到流程 --》2.1 http 头部分解–》2.2 分解url --》2.3获取xml --》2.4获取节点内容 C 定义截取url函数 其中2.4 分解为如下步骤 D 定义获取节点内容的函数 E 定义 调用4 函数得到多个节点内容的函数

关注
打赏
1663161521
查看更多评论
立即登录/注册

微信扫码登录

0.0377s