一个基于工作流基金会的简单 XMPP 客户端






4.44/5 (8投票s)
本文介绍了一个基于工作流基础的简单 XMPP 客户端应用程序。
引言
本文介绍了一个基于 Windows Workflow Foundation 的简单 XMPP 客户端应用程序,它允许发送和接收消息,以及从联系人列表中添加和删除联系人。
背景
可扩展消息处理和存在协议
可扩展消息处理和存在协议 (XMPP) 是一种用于实时通信的开放技术,它使用可扩展标记语言 (XML) 作为交换信息的基本格式。 本质上,XMPP 提供了一种以接近实时的方式将小的 XML 片段从一个实体发送到另一个实体的方法。
XMPP 协议被采用为 RFC 标准,并由以下文档描述
- RFC 3920 可扩展消息处理和存在协议:核心
- RFC 3921 可扩展消息处理和存在协议:即时消息和存在
Windows Workflow Foundation
Windows Workflow Foundation (WF) 是 Microsoft 用于定义、执行和管理工作流的技术。 此技术于 2006 年 11 月首次作为 .NET Framework 3.0 的一部分发布。
WF 是一个特殊的运行时环境,它管理由可恢复的程序语句组成的程序的执行。 在 WF 中,可恢复的程序语句称为活动。 可恢复的程序是活动的组合。 在 WF 中,这样的程序通常被称为工作流。
Using the Code
该项目由两个库和一个 XOML 文件组成:JabberClient.dll(根命名空间是 Jabber.Client
),WorkflowActivities.dll(根命名空间是 Workflow
)和 Sequence.xml。
命名空间 Jabber.Client
Jabber.Client
命名空间包含用于 XMPP 客户端实现的类型,具有最小的功能,如下所示
Jabber.Client.Core.TcpBinder
包装了标准的System.Net.Sockets.Socket
类。Jabber.Client.Core.ClientState
枚举了可能的客户端状态。Jabber.Client.Xml.PacketBuilder
包含用于为 XMPP 服务器请求(身份验证、联系人列表请求、消息发送等)构建 XML 字符串的方法。Jabber.Client.Xml.PacketParser
包含用于解析 XMPP 服务器响应的方法。Jabber.Client.Cryptography.DigestMD5Auth
意味着根据 RFC2831 进行摘要身份验证。Jabber.Client.JabberClient
封装了所有 XMPP 客户端逻辑。
命名空间 Worflow
Worflow
命名空间包括一组活动和辅助类,这些活动和辅助类有助于指定程序算法。 您可以在下面看到主要活动的列表。
Workflow.Activities.Receiver
从Queue
检索消息,借助AssemblyFile
程序集的ReceiveType
类的ReceiveMethod
方法对其进行转换,并调用IWorkflowDataService
接口的OnReceived
方法。Workflow.Activities.Sender
从Queue
检索消息,借助AssemblyFile
程序集的SendType
类的SendMethod
方法对其进行转换,并调用IWorkflowDataService
接口的Send
方法。Workflow.Activities.StateSendAndReceive
发送消息并接收响应。 为了使其工作,该活动需要这些属性:ReceiveMethod
、ReceiveType
、AssemblyFile
、SendMethod
、SendType
和Context
。Context
属性用作 in-out 参数。Workflow.Activities.Sequence
是一种CompositeActivity
类型,它按顺序执行其子活动。Workflow.Activities.Switch
模拟switch
指令。
因此,简单的 XMPP 客户端的 XOML 文件如下所示
<Sequence x:Name="root"
xmlns="http://Workflow/Activities"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wf="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
<Switch x:Name="sw1">
<StateSequence x:Name="Auth" Queue="AuthInputQueue">
<StateSendAndReceive Name="step1_0" AssemblyFile="JabberClient.dll"
SendType="Jabber.Client.Xml.PacketBuilder" SendMethod="AuthStreamHeader"
ReceiveType="Jabber.Client.Xml.PacketParser" ReceiveMethod="AuthStreamHeader1"
Context="{wf:ActivityBind Auth, Path=Context}" />
<StateSendAndReceive Name="step1_1" AssemblyFile="JabberClient.dll"
ReceiveType="Jabber.Client.Xml.PacketParser"
ReceiveMethod="AuthStreamHeader2"
Context="{wf:ActivityBind step1_0, Path=Context}" />
........
</StateSequence>
<Receiver x:Name="Receive" Queue="ReceiveQueue"
AssemblyFile="JabberClient.dll"
ReceiveType="Jabber.Client.Xml.PacketParser"
ReceiveMethod="ResponseMessage" />
<Sender x:Name="Send" Queue="SendQueue"
AssemblyFile="JabberClient.dll"
SendType="Jabber.Client.Xml.PacketBuilder"
SendMethod="ChatMessage"/>
<Sender x:Name="Status" Queue="StatusQueue"
AssemblyFile="JabberClient.dll"
SendType="Jabber.Client.Xml.PacketBuilder"
SendMethod="PresenceShow"/>
<Sender x:Name="Roster" Queue="RosterQueue"
AssemblyFile="JabberClient.dll"
SendType="Jabber.Client.Xml.PacketBuilder"
SendMethod="Roster"/>
<Sender x:Name="Subscribe" Queue="RosterQueue"
AssemblyFile="JabberClient.dll"
SendType="Jabber.Client.Xml.PacketBuilder"
SendMethod="Subscribe"/>
<Sender x:Name="Unsubscribe" Queue="RosterQueue"
AssemblyFile="JabberClient.dll"
SendType="Jabber.Client.Xml.PacketBuilder"
SendMethod="Unsubscribe"/>
</Switch>
</Sequence>
从 XOML 文件可以看出,StateSequence
活动根据 RFC2831 在 XMPP 服务器上执行客户端身份验证。 Context
属性的动态绑定用于子活动中。
下面显示了使用简单 XMPP 客户端的示例
....
using Jabber.Client;
using Jabber.Client.Core;
....
using (JabberClient jabber =
new JabberClient("jabber.org", "vba32cc", "1234qwer"))
{
//subscribe to events
jabber.Authentificated += new EventHandler(jabber_Authentificated);
jabber.RosterReceived += new RosterHandler(jabber_RosterReceived);
jabber.MessageReceived += new MessageHandler(jabber_MessageReceived);
Console.WriteLine("Authentification...");
jabber.Auth();
string s = Console.ReadLine();
Console.WriteLine("Client state={0}", jabber.State);
while (!string.IsNullOrEmpty(s))
{
if (jabber.State == ClientState.Authentificated)
{
Contact contact = new Contact("", "veleslaff@jabber.ru");
jabber.AddToContacts(contact); //Add to contacts
jabber.SetStatusForContact(contact, UserStatus.Online);//Set status
jabber.Send(contact, s); //Send message
jabber.Contacts(); //Get roster list
}
s = Console.ReadLine();
}
}
....
关注点
工作流库中的错误处理和主机程序的通知需要改进。 Jabber.Client.Xml
命名空间中的类需要重构。
历史
- 2009 年 12 月 27 日:具有基本功能的简单 XMPP 客户端的第一个版本。
- 2009 年 12 月 28 日:更新了示例项目。