agsXMPP Software Design

原文:http://www.cnblogs.com/hunts/archive/2006/12/11/588912.html

agsXMPP致力于创建一个轻量、快速的跨平台类库,用于XMPP协议。

通过下面的三项技术,agsXMPP达到了这个目标。

  1. 异步套接字
  2. 与工厂模式结合的快速XML解析器
  3. 自有的轻量级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 own packet types

下面的小例子中我们将要创建一个我们自己的扩展,通过XMPP网络发送天气信息。最简单的方法是将天气的数据信息嵌入到一个message节中。嵌入了天气信息的新XML message如下所示:

< message xmlns = " jabber:client "  to = " romeo@montage.net " >
    
< weather xmlns = " 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
{
    
public class Weather : Element
    
{
        
public Weather()
        
{
            
this.TagName = "weather";
            
this.Namespace = "agsoftware:weather";
        }

        
public Weather(int humidity, int temperature) : this()
        
{
            
this.Humidity = humidity;
            
this.Temperature = temperature;
        }

        
public int Humidity
        
{
            
get return GetTagInt("humidity"); }
            
set { SetTag("humidity", value.ToString()); }
        }

        
public int Temperature
        
{
            
get return GetTagInt("temperature"); }
            
set { SetTag("temperature", value.ToString()); }
        }

    }

}

然后在元素工厂中注册这个新类。如果不注册,在解析XML流时XML解析器就不会weather对象。我们通过下面的代码注册该类:

agsXMPP.Factory.ElementFactory.AddElementType( " weather " ,
" agsoftware:weather " typeof (Weather));

我们在使用agsXMPP处理其它事件时,应该先注册我们自己的元素。

现在我们能够创建自己的weather message,然后发送:

Weather weather  =   new  Weather( 90 57 );
Jid to 
=   new  Jid( " romeo@montage.net " );
Message msg 
=   new  Message();
msg.To 
=  to;
//  Add our weather Element
msg.AddChild(weather);
//  Send the message
XmppCon.Send(msg);

接收此message的另一个应用程序可以像OnMessage handler那样访问到我们的定制数据:

private   void  XmppCon_OnMessage( object  sender, Message msg)
{
    
if  (msg.HasTag( typeof (Weather)))
    {
        Weather weather 
=  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':

< iq from =' romeo@montagne.net' to =' weather.mortagne.net' type =' get' id =' agsXMPP_1' >
    
< query xmlns =' agsoftware:weather' >
        
< zip > 74080 </ zip >
    
</ query >
</ iq >

接着weather service查找该zip code的天气数据,然后返回结果给Romeo:

< iq to =' romeo@montagne.net' from =' weather.mortagne.net' type =' result' id =' agsXMPP_1' >
    
< query xmlns =' agsoftware:weather' >
        
< humidity > 90 </ humidity  >
        
< temperature > 57 </ temperature >
        
< zip > 74080 </ zip >
    
</ query >
</ iq >

Weather.cs的源代码:

using  System;
using  agsXMPP.Xml;
using  agsXMPP.Xml.Dom;

public   class  Weather : Element
{
    
public Weather()
    
{
        
this.TagName = "query";
        
this.Namespace = "agsoftware:weather";
    }

    
public int Humidity
    
{
        
get return GetTagInt("humidity"); }
        
set { SetTag("humidity", value.ToString()); }
    }

    
public int Temperature
    
{
        
get return GetTagInt("temperature"); }
        
set { SetTag("temperature", value.ToString()); }
    }

    
public int Zip
    
{
        
get return GetTagInt("zip"); }
        
set { SetTag("zip", value.ToString()); }
    }

}

WeatherIq.cs的源代码:

using  System;
using  agsXMPP;
using  agsXMPP.protocol.client;

public   class  WeatherIq : IQ
{
    
private Weather m_Weather = new Weather();

    
public WeatherIq()
    
{
        
base.Query = m_Weather;
        
this.GenerateId();
    }


    
public WeatherIq(IqType type)
        : 
this()
    
{
        
this.Type = type;
    }


    
public WeatherIq(IqType type, Jid to)
        : 
this(type)
    
{
        
this.To = to;
    }


    
public WeatherIq(IqType type, Jid to, Jid from)
        : 
this(type, to)
    
{
        
this.From = from;
    }


    
public new Weather Query
    
{
        
get
        
{
            
return m_Weather;
        }

    }

}

当然我们要在工厂里注册Weather对象,使用下面代码:

agsXMPP.Factory.ElementFactory.AddElementType( " weather " ,
" agsoftware:weather " typeof (Weather));

Romeo的客户端使用WeatherIq对象创建了请求Iq包:

WeatherIq wIq  =   new  WeatherIq(IqType. get );
wIq.To 
=   new  Jid( " weather.mortagne.net " );
wIq.From 
=   new  Jid( " romeo@montagne.net " );
wIq.Query.zip 
=   74080 ;
//  Send the message
XmppCon.Send(wIq);

weather service在Iq handler中接收此请求,然后把响应发回给Romeo。在weather service中获得请求信息,然后编辑:

private   void  XmppCon_OnIq( object  sender, agsXMPP.Xml.Dom.Node e)
{
    IQ iq 
= e as IQ;
    Element query 
= iq.Query;

    
if (query != null)
    
{
        
if (query.GetType() == typeof(Weather))
        
{
            
// its a Weather IQ
            Weather weather = query as Weather;
            
if (iq.Type == IqType.get)
            
{
                Console.WriteLine(weather.Zip.ToString());
                
// read the zip code and lookup the weather
                
// data for this zip code
                
// . . . .
                iq.SwitchDirection();
                iq.Type 
= IqType.result;
                weather.Humidity 
= 90;
                weather.Temperature 
= 57;
                
// Send the result back to romeo
                XmppCon.Send(iq);
            }

        }

    }

}

Romeo接收到响应,然后通过我们的weather对象的属性访问到天气数据。 



Google
<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值