XMPP协议即时通讯工具实现原理.docx

上传人:b****5 文档编号:11881041 上传时间:2023-04-08 格式:DOCX 页数:10 大小:175.23KB
下载 相关 举报
XMPP协议即时通讯工具实现原理.docx_第1页
第1页 / 共10页
XMPP协议即时通讯工具实现原理.docx_第2页
第2页 / 共10页
XMPP协议即时通讯工具实现原理.docx_第3页
第3页 / 共10页
XMPP协议即时通讯工具实现原理.docx_第4页
第4页 / 共10页
XMPP协议即时通讯工具实现原理.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

XMPP协议即时通讯工具实现原理.docx

《XMPP协议即时通讯工具实现原理.docx》由会员分享,可在线阅读,更多相关《XMPP协议即时通讯工具实现原理.docx(10页珍藏版)》请在冰豆网上搜索。

XMPP协议即时通讯工具实现原理.docx

XMPP协议即时通讯工具实现原理

XMPP协议--即时通讯工具实现原理(服务器,客户端)

分类:

C#jabber/XMPP2010-12-1021:

26292人阅读评论(0)收藏举报

第一篇:

.net平台 基于 XMPP协议的即时消息服务端简单实现

昨天抽空学习了一下XMPP,在网上找了好久,中文的资料太少了所以做这个简单的例子,今天才完成。

公司也正在准备开发基于XMPP协议的即时通讯工具所以也算是打一个基础吧!

如果你还没有了解过XMPP请先阅读附录中链接的文章,本实例是基agsXMPP上开发的,agsXMPP是C#写的支持开源XMPP协议软件,我们可以在agsXMPP上快速构建自已的即时通讯平台,我的这个例子只是修改了服务器端,因为agsXMPP本身自带的服务器端没有实现聊天功能、签名和登录密码认证。

服务器端XmppSeverConnection类事件

//在流开始时触发,一般是最初的响应流

streamParser.OnStreamStart += new StreamHandler(streamParser_OnStreamStart);

//在流结束时触发,一般是发送

stream>并关闭套接字连接streamParser.OnStreamEnd += new StreamHandler(streamParser_OnStreamEnd);

//在接收到流结点时触发,这是用得最多的,常用的消息,出席消息,< IQ>请求应答消息都在这里处理

streamParser.OnStreamElement += new StreamHandler(streamParser_OnStreamElement);

 

//此处处理大部份的消息,包括消息路由

private void streamParser_OnStreamElement(object sender, Node e)

        {

            Console.WriteLine("OnStreamElement:

 " + e.ToString());

            if (e.GetType() == typeof(Presence))

            {

             // 路由presences节

            }

            else if (e.GetType() == typeof(Message))

            {

                // 路由messages节

            }

            else if (e.GetType() == typeof(IQ))

            {

                //处理IQ节

            }

        }

 

 /// 

        /// IQ节处理函数

        /// 

        /// .

        private void ProcessIQ(IQ iq)

        {

            if (iq.Query.GetType() == typeof(Auth))

            {

               Auth auth = iq.Query as Auth;

                this.Username = auth.Username.ToString();

                switch (iq.Type)

                {

                    case IqType.get:

                        iq.SwitchDirection();

                        iq.Type = IqType.result;

                        auth.AddChild(new Element("password"));

                        auth.AddChild(new Element("digest"));

                        Send(iq);

                        break;

                    case IqType.set:

                        // 进行登录认证

                        if (AccountBus.CheckLogin(auth.Username, auth.Digest, this.SessionId))

                        {

                            iq.SwitchDirection();

                            iq.Type = IqType.result;

                            iq.Query = null;

                            Send(iq);

                            Console.WriteLine(auth.Username + "登录了" + "   登录时间:

" + System.DateTime.Now.ToString());

                        }

                       else

                        {

//登录失败返回错误信息

                            iq.SwitchDirection();

                            iq.Type = IqType.error;

                            iq.Query = null;

                            Send(iq);

                        }

                        break;

                }

            }

            else if (iq.Query.GetType() == typeof(Roster))

            {

                ProcessRosterIQ(iq);

            }

        }

 

/// 

        /// 处理IQ节的杂项数据.

        /// 

        /// The iq.

        private void ProcessRosterIQ(IQ iq)

        {

            if (iq.Type == IqType.get)

            {

                // 发送IQ节的杂项数据

              //这里我用来下载好友列表

                iq.SwitchDirection();

                iq.Type = IqType.result;

                List friendList = new List();

                friendList = AccountBus.GetFriendName(this.username);

                foreach (string str in friendList)

                {

                    RosterItem ri = new RosterItem();

                    ri.Name = str.Trim();

                    ri.Subscription = SubscriptionType.both;

                    ri.Jid = new agsXMPP.Jid(str.Trim() + "@localhost");

                    ri.AddGroup("localhost");

                    iq.Query.AddChild(ri);

                }

                Send(iq);

            }

        }

服务器端开启监听5222端口

 while (running)

                {

                    ////

                    allDone.Reset();

                    // Start an asynchronous socket to listen for connections.

                    Console.WriteLine("等待连接...");

                    listener.BeginAccept(new AsyncCallback(AcceptCallback), null);

                    //// 等待客户端连接                    

                     allDone.WaitOne();

                }

如果收到客户端请求就异步调用AcceptCallback初始化套接字连接

并为客户端建立一个通信线程,新建初始化套接字连接采用异步调

用读取套接字信息

 public XmppSeverConnection(Socket sock)

            :

 this()

        {

            m_Sock = sock;

            m_Sock.BeginReceive(buffer, 0, BUFFERSIZE, 0, new AsyncCallback(ReadCallback), null);

            m_Sock.SendTimeout = 100;

        }

客户端与服务器端的交互过程

1客户端异步向服务器端发送连接请求

streamto='localhost'xmlns='jabber:

client'xmlns:

stream='http:

//etherx.jabber.org/streams'version='1.0'xml:

lang='en'>

2服务器端收到请求,初始化回应流,并随机生成一相SessionID

 

streamxmlns:

stream="http:

//etherx.jabber.org/streams"from="localhost"id="30e3b8c0">

3等待服务器返回消息后客户端发送用户名(由于在客户端采用了异步调用

方式,所以UI界面感觉不到等待) 

client"id="agsXMPP_1"type="get"to="localhost">

iq:

auth">test

4服务器端收到用户名等待用户提供密码

client"from="localhost"type="result"id="agsXMPP_1">

iq:

auth">test

5客户端提供加密后的密码

client"id="agsXMPP_2"to="localhost"type="set">

iq:

auth">test

e66557d2b67256bf7e9b317a51b6101674a56b5e

MiniClient

6服务器端从数据库验证用户名和密码,并返回结果

iqxmlns="jabber:

client"from="localhost"type="result"id="agsXMPP_2"/>

7如果返回错误,客户端提示并终断连接,否则客户端发送响应数据

8 服务器端返回数据

9 客户端发送状态,

10服务器收到状态,发送IQ节并通知其它用户.

项目解决方案和类图

附录:

推荐使用Pandion作为客户端

服务器端下载      客户端下载

agsXMPP 源码下载 

XMPPRFC3920 可扩展消息出席协议 

jabber官方网站

 

第二篇:

基于 XMPP协议的服务器端 文件互传的简单实现

    昨天我们讲了客户端实现用户互发消息的原理,今天我们继续学习一下基于XMPP协议的文件传输,首先我们假设用户已经登录,这里我们假设ClinetSend对ClinetReceive 发送文件,这里记录了ClinetSend的发送和接收XML流记录

1、发送请求表示要向Clinettest发送文件,并发送文件大小和文件名

SEND:

 

client" id="agsXMPP_6" to="Receive @localhost/" type="set">

  

//jabber.org/protocol/si" profile="http:

//jabber.org/protocol/si/profile/file-transfer" id="b3b5f49c-8a94-49e2-908a-3de694b98af0">

    

//jabber.org/protocol/si/profile/file-transfer" name="MiniClient.exe.config" size="382">   

   

//jabber.org/protocol/feature-neg">

    

x:

data" type="form">

       

          

             http:

//jabber.org/protocol/byReceive reams

         

       

     

   

 

2、Receive 收到Send发实来的请求后,发送出响应流

RECV:

 

client" to="Send@localhost" type="result" id="agsXMPP_6">

 

//jabber.org/protocol/si" id="b3b5f49c-8a94-49e2-908a-3de694b98af0">

     

//jabber.org/protocol/feature-neg">

       

x:

data" type="submit">

          

           http:

//jabber.org/protocol/byReceive reams

         

       

    

 

3、Send收到Receive 愿意接收的响应后,发出如下XML流

SEND:

 

client" id="agsXMPP_7" to="Receive@localhost" type="set">

      

//jabber.org/protocol/bySendreams" sid="71f1b875-4d84-429c-b39d-7dabcd400f3d">

         

         

      

注意这里注要是代理的设置,agsXMPP 自带的客户端是使用代理传输数据的,所以必须对其做相应的修改,使其支持局域网内支持发送文件.

下面我们来看一下服务器端是如何路由消息的呢?

从上面所发送的XML流我们可以看出,实际上用户传送文件所发送的都是IQ节,我们必须对IQ节进行路由才能使其找到相应的接收者 ,所以我们需要在XmppServerConnection类中添加如下代码:

 

private void ProcessIQ(IQ iq)

        {

//传送文件得理

  if (iq.Query == null)

            {

                if(iq.Type == IqType.result)

                    this.Send(iq);

                ProcessOobIQ(iq);

            }else if (iq.Query.GetType() == typeof(Auth))

            {

                Auth auth = iq.Query as Auth;

                this.Username = auth.Username.ToString();

                switch (iq.Type)

                {

                    case IqType.get:

                        iq.SwitchDirection();

                        iq.Type = IqType.result;

                        auth.AddChild(new Element("password"));

                        auth.AddChild(new Element("digest"));

                        Send(iq);

                        break;

                    case IqType.set:

                        // Here we should verify the authentication credentials

                        if (AccountBus.CheckLogin(auth.Username, auth.Digest, this.SessionId))

                        {

                            iq.SwitchDirection();

                            iq.Type = IqType.result;

                            iq.Query = null;

                            Send(iq);

                            Console.WriteLine(auth.Username + "登录了" + "   登录时间:

" + System.DateTime.Now.ToString());

                        }

                        else

                        {

                          //  iq.SwitchDirection();

                            iq.Type = IqType.error;

                            iq.Query = null;

                            Send(iq);

                        }

                        break;

                }

            }

            else if (iq.Query.GetType() == typeof(Roster))

            {

                ProcessRosterIQ(iq);

            }//用代理传送文件处理

            else if(iq.Query.FirstChild !

=null)

            {

               // iq.SwitchDirection();

               // //iq.Type = IqType.result;

               // //

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 其它课程

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1