65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.44/5 (8投票s)

2009年12月27日

CPOL

3分钟阅读

viewsIcon

66099

downloadIcon

3800

本文介绍了一个基于工作流基础的简单 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.ReceiverQueue 检索消息,借助 AssemblyFile 程序集的 ReceiveType 类的 ReceiveMethod 方法对其进行转换,并调用 IWorkflowDataService 接口的 OnReceived 方法。
  • Workflow.Activities.SenderQueue 检索消息,借助 AssemblyFile 程序集的 SendType 类的 SendMethod 方法对其进行转换,并调用 IWorkflowDataService 接口的 Send 方法。
  • Workflow.Activities.StateSendAndReceive 发送消息并接收响应。 为了使其工作,该活动需要这些属性:ReceiveMethodReceiveTypeAssemblyFileSendMethodSendTypeContextContext 属性用作 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 日:更新了示例项目。
© . All rights reserved.