原文:http://www.cnblogs.com/hunts/archive/2006/12/11/588912.html
agsXMPP致力于创建一个轻量、快速的跨平台类库,用于XMPP协议。
通过下面的三项技术,agsXMPP达到了这个目标。
- 异步套接字
- 与工厂模式结合的快速XML解析器
- 自有的轻量级XML Dom,作为所有agsXMPP协议类的基础
我们为什么不直接所用Microsoft的System.Xml命名空间里的类呢?
因为我们决定创建自己的轻量级的Xml Dom,能够飞快地运作,特别是在像PPC's和Smartphones这样的嵌入式设备上。
XmlTextReader有利于SAX-like的解析。但是Microsoft在.NET1.1的SP1中做了下改变,这使得我们不能够再使用它来解析网络流。所以我们需要另外的XML解析器。
类库的惊人之处在哪?
一旦从套接字接收到数据,该数据便由sax-like XML解析器解析。此解析器使用工厂模式来创建agsXMPP协议类相关的元素。
示例:
套接字接收到一条信息,将比特流推送至解析器。XML解析器探测到隶属于jabber:client命名空间中名字为message的开标签符。在元素创建前,解析器在工厂散列表中做个查找。这样就创建了agsXMPP.protocol.client.Message类的一个实例。如果表中不存在name/namespace的绑定,则会创建agsXMPP.Xml.Element的一个实例。
所有的XMPP协议类都派生自agsXMPP.Xml.Element。他们都是在内存中保持XML树的'abstract'元素。所有的属性都是'realtime properties'。在我们要读取消息体,调用消息体属性时,类将会实时查找<body/>元素。
Creating your ownpacket types
下面的小例子中我们将要创建一个我们自己的扩展,通过XMPP网络发送天气信息。最简单的方法是将天气的数据信息嵌入到一个message节中。嵌入了天气信息的新XML message如下所示:
<
messagexmlns
=
"
jabber:client
"
to
=
"
[email protected]
"
>
<
weatherxmlns
=
"
agsoftware:weather
"
>
<
humidity
>
90
</
humidity
>
<
temperature
>
57
</
temperature
>
</
weather
>
</
message
>
我们要给这个新的协议创建一个新的命名空间和3个新元素:weather、humidity和temperature
首先,我们给我们定制的XML元素创建一个新的类weather.cs,派生自agsXMPP.Xml.Dom.Element。
using
System;
using
agsXMPP.Xml.Dom;
namespace
MiniClient
![](http://img.e-com-net.com/image/product/8bf85857a9e14d23a651e7c8ef856bcc.gif)
{
publicclassWeather:Element
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
publicWeather()
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
this.TagName="weather";
this.Namespace="agsoftware:weather";
}
publicWeather(inthumidity,inttemperature):this()
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
this.Humidity=humidity;
this.Temperature=temperature;
}
publicintHumidity
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
get
{returnGetTagInt("humidity");}
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
set
{SetTag("humidity",value.ToString());}
}
publicintTemperature
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
get
{returnGetTagInt("temperature");}
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
set
{SetTag("temperature",value.ToString());}
}
}
}
然后在元素工厂中注册这个新类。如果不注册,在解析XML流时XML解析器就不会weather对象。我们通过下面的代码注册该类:
agsXMPP.Factory.ElementFactory.AddElementType(
"
weather
"
,
"
agsoftware:weather
"
,
typeof
(Weather));
我们在使用agsXMPP处理其它事件时,应该先注册我们自己的元素。
现在我们能够创建自己的weather message,然后发送:
Weatherweather
=
new
Weather(
90
,
57
);
Jidto
=
new
Jid(
"
[email protected]
"
);
Messagemsg
=
new
Message();
msg.To
=
to;
//
AddourweatherElement
msg.AddChild(weather);
//
Sendthemessage
XmppCon.Send(msg);
接收此message的另一个应用程序可以像OnMessage handler那样访问到我们的定制数据:
private
void
XmppCon_OnMessage(
object
sender,Messagemsg)
{
if
(msg.HasTag(
typeof
(Weather)))
{
Weatherweather
=
msg.SelectSingleElement(
typeof
(Weather))
as
Weather;
Console.WriteLine(weather.Temperature.ToString());
Console.WriteLine(weather.Humidity.ToString());
}
}
现在我们创建了我们第一个自己的(信息)包,包含了一个message节。接下去我们要创建基于Iqs的小型weather service。
service的raw xml protocol:
Romeo向weather service请求了他城市的天气信息,zip code为'74080':
<
iqfrom
='
[email protected]'to
='
weather.mortagne.net'type
='
get'
id
='
agsXMPP_1'
>
<
queryxmlns
='
agsoftware:weather'
>
<
zip
>
74080
</
zip
>
</
query
>
</
iq
>
接着weather service查找该zip code的天气数据,然后返回结果给Romeo:
<
iqto
='
[email protected]'from
='
weather.mortagne.net'type
='
result' id
='
agsXMPP_1'
>
<
queryxmlns
='
agsoftware:weather'
>
<
humidity
>
90
</
humidity
>
<
temperature
>
57
</
temperature
>
<
zip
>
74080
</
zip
>
</
query
>
</
iq
>
Weather.cs的源代码:
using
System;
using
agsXMPP.Xml;
using
agsXMPP.Xml.Dom;
![](http://img.e-com-net.com/image/product/46339e8aae704cb1a8b93e7cd90036c0.gif)
public
class
Weather:Element
![](http://img.e-com-net.com/image/product/8bf85857a9e14d23a651e7c8ef856bcc.gif)
{
publicWeather()
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
this.TagName="query";
this.Namespace="agsoftware:weather";
}
publicintHumidity
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
get
{returnGetTagInt("humidity");}
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
set
{SetTag("humidity",value.ToString());}
}
publicintTemperature
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
get
{returnGetTagInt("temperature");}
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
set
{SetTag("temperature",value.ToString());}
}
publicintZip
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
get
{returnGetTagInt("zip");}
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
set
{SetTag("zip",value.ToString());}
}
}
WeatherIq.cs的源代码:
using
System;
using
agsXMPP;
using
agsXMPP.protocol.client;
![](http://img.e-com-net.com/image/product/46339e8aae704cb1a8b93e7cd90036c0.gif)
public
class
WeatherIq:IQ
![](http://img.e-com-net.com/image/product/8bf85857a9e14d23a651e7c8ef856bcc.gif)
{
privateWeatherm_Weather=newWeather();
![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
publicWeatherIq()
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
base.Query=m_Weather;
this.GenerateId();
}
![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
publicWeatherIq(IqTypetype)
:this()
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
this.Type=type;
}
![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
publicWeatherIq(IqTypetype,Jidto)
:this(type)
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
this.To=to;
}
![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
publicWeatherIq(IqTypetype,Jidto,Jidfrom)
:this(type,to)
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
this.From=from;
}
![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
publicnewWeatherQuery
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
get
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
returnm_Weather;
}
}
}
当然我们要在工厂里注册Weather对象,使用下面代码:
agsXMPP.Factory.ElementFactory.AddElementType(
"
weather
"
,
"
agsoftware:weather
"
,
typeof
(Weather));
Romeo的客户端使用WeatherIq对象创建了请求Iq包:
WeatherIqwIq
=
new
WeatherIq(IqType.
get
);
wIq.To
=
new
Jid(
"
weather.mortagne.net
"
);
wIq.From
=
new
Jid(
"
[email protected]
"
);
wIq.Query.zip
=
74080
;
//
Sendthemessage
XmppCon.Send(wIq);
weather service在Iq handler中接收此请求,然后把响应发回给Romeo。在weather service中获得请求信息,然后编辑:
private
void
XmppCon_OnIq(
object
sender,agsXMPP.Xml.Dom.Nodee)
![](http://img.e-com-net.com/image/product/8bf85857a9e14d23a651e7c8ef856bcc.gif)
{
IQiq=easIQ;
Elementquery=iq.Query;
![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
if(query!=null)
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
if(query.GetType()==typeof(Weather))
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
//itsaWeatherIQ
Weatherweather=queryasWeather;
if(iq.Type==IqType.get)
![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
{
Console.WriteLine(weather.Zip.ToString());
//readthezipcodeandlookuptheweather
//dataforthiszipcode
//....
iq.SwitchDirection();
iq.Type=IqType.result;
weather.Humidity=90;
weather.Temperature=57;
//Sendtheresultbacktoromeo
XmppCon.Send(iq);
}
}
}
}
Romeo接收到响应,然后通过我们的weather对象的属性访问到天气数据。
<!-- Search Google -->
|
<!-- google_ad_client = "pub-7330597899926046"; google_ad_format = "350x30_sdo"; google_link_target = 2; google_color_bg = "ffffff"; google_color_link = "000000"; google_encoding = "GB2312"; //--> |
<!-- Search Google --> <!-- google_ad_client = "pub-7330597899926046"; google_ad_slot = "8791774696"; google_ad_width = 468; google_ad_height = 60; //-->