ok,我们已经搞清XMPP节是怎么收到的了,也知道收到后XmppEngineImpl:HandleInput会被调用,然后就看到今天的重点:XML解析
HandleInput会调用XmppStanzaParser.Parse() 解析XML,后者调用XmlParser.Parse(),这个函数即调用了expat库函数,根据expat的使用方法,接下来的事都是回调函数干的,可是他们在哪?
我们回去看看这个XmppStanzeParser是个啥东西呢?注意它里面定义了这样一个类
这是适配器模式,将XmppStanzeParser接口转换为XmlParseHandler类型的。显然这些都是回调函数,可是流程是什么样的?我们得看看这个handler的定义。
这家伙是个纯虚基类,然后发现XmlParser就定义在它下面(这是个好习惯,一个接口和使用它的类定义在一起),而XmlParse里面有个成员变量pxph_是XmlParseHandler 类型的。然后再看看这里
看看最下面这4个函数,注释写的“expat callbacks”,表明它们是回调函数的发源地。我们随便挑个函数,就ExpatStartElement去看看,
看最下面的pxph_->StartElement!
所以XmlParse是真正做XML解析工作的,而XmppStanzaParser通过ParserHandler适配成XmlParserHandler接口来接收XmlParser的回调。可是被回调后XmppStanzeParser会怎么办呢?
看看它的4个回调函数,发觉有两个成员变量一直被使用:XmppStanzaParseHandler * psph_和XmlBuilder builder_
XmppStanzaParseHandler又是个纯虚基类,它唯一的派生类定义在XmppEngineImpl中,定义如下
啊哈,似曾相识的感觉,这又是个适配器!将XmppEngineImlp适配成XmppStanzaParseHandler以接收XmppStanzaParser的回调,回调后XmppEngineImpl的IncomingStart,IncomingStanza,IncomingEnd中的某个将被调用,随即开始消息处理
而第二个变量XmlBuilder看看它的函数名就知道,这是用来生成XML回复的,可是回复是怎么发出的?我们找个回复函数,XmppEngineImpl::SendStanza看着比较典型,就它了:
如果还在登陆调用OutgoingStanza,否则是InternalSendStanza,我们看看一般情况,即调用InternalSendStanza,这函数只是调用XmlPrinter把XML输出到output_的流里,没有任何发送啊。回来看看SendStanza函数,它有个Enterexit看着很奇怪,只感觉类似资源自动释放,我们去看看,果然,它的析构函数里有大量代码,它检查是否需要发送数据,如果需要则调用WriteOutput发送。此外还有是否需要关闭连接==,可能是多个函数需要实现这样的功能,所以被封装起来,做成这种形式
原文链接:https://www.f2er.com/xml/297863.html