IM的集成开发

by 里克 2008年03月07日 jabber twitter xmpp xmpp4r

写在前面 :

这篇文章准备了挺长时间,因为在IM集成开发上是个新手,所以需要看狠多资料来理解各种概念,还在在自己的机器上做一下试验。下面就是对一些资料的笔记总结。

非常感谢分享自己开发经验的朋友。

第一部分:XMPP,第二部分:XMPP4R,第三部分:如何实现IM集成开发的探讨。本篇主体来自rubyfleebie.com几篇非常好的文章。

第一部分:XMPP

1、twiter带来了什么?

twitter已经红了很长时间,而且国内国外的跟风网站和fans已经出来许多,前一篇博客里提到的Twitterverse.com,就是一个fans站。如果你之前和我一样对twitter了解很少,可以看看下面的连接,是对twitter的解释。

link:http://baike.baidu.com/view/843376.htm

twitter的亮点,以及效仿网站 的主要技术,就是IM功能集成到项目中。比如9fav.com,向qq里发去一条网址,就会自动加到个人的网址收藏夹中。

2、XMPP

现在该是XMPP登场了。XMPP是eXtensible Messaging and Presence Protocol(可扩展消息处理现场协议)的缩写,使用该协议,可以以XML格式进行消息传递。

link:http://baike.baidu.com/view/189676.htm

XMPP的前身是Jabber,一个开源形式组织产生的网络即时通信协议。Jabber的开源,使得你可以使用Jabber客户端,如PidginSparkGoogle talk(其实Gtalk不是Jabber客户端),Gajim,登陆Jabber服务器,或者登陆你自己搭建的服务器(下一篇文章将介绍)。常听别人说可以把多个聊天软件集成到一起吧。其实原理就是使用Jabber客户端,登陆到Jabber服务器,Jabber服务器可以与其他的聊天服务器进行沟通,比如MSN,Gtalk,AIM等,这样你就可以在自己的Jabber客户端中与他们进行联系了。Server-to-server是Jabber架构的重要功能!

下图是我连接自己的机器(我自己建的Jabber服务器),然后集成了msn和gtalk的用户过来后的界面。

spark截图

这里,列出了公开的Jabber服务器,大家可以登陆试试看。

3、XML的意义:Streams 和 Stanzas

在开始的部分,介绍一下原文另一款中文翻译,这篇文章对于快速的学习IM集成开发有很大的帮助,学习的朋友建议看一下。

下面是对那篇翻译的引用,作者:IceskYsl

在Jabber的消息交换过程中,有两种概念比较重要的是Streams 和 Stanzas。
Streams 是Jabber客户端和其服务器之间的联通、交换消息的容器(例如GoogleTalk和gmail.com ),以 XML格式的开始,以结束。而两者之间交换的各种消息都是其他格式的XML节点(被称为 stanzas),都被包含在这个容器中,当联通的两端任何一方退出登录的时候,就发送给另外一方。比如我关闭 GoogleTalk客户端,其就会发送给gmail.com通知结束会话。
bq. PS:这里需要强调的是stream不会出现在用户A和用户B之间,而仅仅存在于您使用的*客户端*和其对应的*服务器*端之间。
Stanzas节点包含的的就是用户A和用户B直接需要交换的消息,一般常用的有3个格式的,分别为:


  1. Message

  2. Presence

  3. IQ

*Message*类的Stanzas用来在两个用户间交换消息,比如*用户A*(iceskysl@someserver.com/home)给*用户B*(1sters@someotherserver.com/home)发送一条消息“1sters… are you there?”,其包装以后的格式类似于:
bq.

1sters… are you there?



我们再来看看,这个过程是怎么样的,当*用户A*发送消息的时候,其消息先到someserver.com,然后someserver.com看到其消息是发给1sters@someotherserver.com/home的,于是将其传递给*用户B*的服务器someotherserver.com,然后,由someotherserver.com发送给*用户B*。

*presence *类的stanza 是当用户的状态(Idle, Offline, Available, Do not disturb等等 )发生改变时发送的。

IQ (Info / Query)类的stanzas是用来查看对方信息的,比如用户A想查看用户B的信息,就会发送一个“获取消息”的IQ stanza,用户B收到后,会回一个包含用户A查询的信息的IQ stanza。

第二部分:XMPP4R

XMPP4R是用Ruby实现XMPP客户端库文件,和其他的Jabber客户端软件一样,XMPP4R发送,接收和管理XML信息(stanzas)。

在下面的代码中,演示了如何用XMPP4R实现客户端功能。内容还是参考上面提到的IceskYsl的翻译。

1、 登录服务器


client = Jabber::Client.new(Jabber::JID::new(“itechtag.notify@gmail.com/rebot”)) #初始化一个实例

client.connect #连接到服务端 client.auth(“my_extremely_secret_password”) #验证密码 client.send(Presence.new.set_type(:available)) #更新状态

第四行,我们发送第一个stanza给服务器,告诉服务器:我在这里了。这样其他好友就会看到我的状态位“可用”了。

2、 发送消息

接下来看看如何发送消息给我的好友


msg = Jabber::Message::new(“iceskysl@gmail.com”, “Hello… ice?”) #这里是接收者的Jid和需要发送的消息

msg.type=:chat #这里设置消息的类型 client.send(msg) #发送出去

怎么样,很简单吧,但是需要提醒您的是,最好是把消息的类型设置为"chat",因为不同的客户端对消息的类型的处理方式是不一样的,比如Gajim 用户每收到一个标识为“normal”的消息,都会重新弹出一个窗口显示,而不会在原来打开的窗口中继续显示。

3、添加好友

前面我们看到了,如何发送消息给另外一个人,但是当这个人不在你的好友列表中时,可能他并不能收到您的消息(也依赖不同的客户端,比如GoogleTalk就会先发送一个“加为好友”的请求),所以最保险的做法是先把这个人加为自己的好友,代码如下:


pres = Jabber::Presence.new.set_type(:subscribe).set_to(“john@someserver.com”)

client.send(pres)

如上代码发送我们的添加john为好友的请求(_subscription _),但是什么时候返回?又返回什么内容呢?还好,XMPP4r不会一直等待其返回,也就是说上面这个过程是异步的,因为我们不晓得对方是否在线,是否会立即给我回复等等,但是我们又如何知道对方的反馈呢?就需要介绍XMPP4r的另外一个特性,*callbacks*.

4、Callbacks 监听

Callbacks 是个很重要的东西,他运行在自己的线程中,也就是说不会干扰主线程的运行,这个特性对我们非常重要的,因为这其实就保证了一个异步的过程,我们的主线程并 不需要等到请求的响应就可以继续下去做其他的事情,而Callbacks不断的监听以取得需要的响应。

回到刚才那个添加好友的地方,我们给john发送了添加好友的请求,我们怎么取得其响应呢?我们也说了,我们的主线程不会一直等待反馈,所以需要另外一种机制以保证有响应的时候我们可以及时的知道,这个就是Callbacks要干的事情。

由于“添加好友”这个请求(subscription request)对应的callback为“add_update_callback”,所以我们需要在“添加成功”注册这个callback监听:


client.add_update_callback do |presence|

if presence.from == “john@someserver.com” && presence.ask == :subscribe client.send(presence.from, “好友添加成功”) end end

Xmpp4r提供了很多类似的Callbacks,比如一个人给我发消息时,我们可以使用add_message_callback监听:


client.add_message_callback do |m|

if m.from == “john@someserver.com” #得到john的消息 m.body #输出john的消息 end


另外,还有当对方状态发生变化的时候,我们可以用add_presence_callback来监视,类似代码这样:

client.add_presence_callback do |old_presence, new_presence|

if new_presence.from == “john@someserver.com” && new_presence.show == :dnd msg = Message::new(“john@someserver.com”, “对方为免打扰模式哦”) msg.type=:chat client.send(msg) end

上面提到的另一款中文翻译里面,后面部分讲了“技能云”的IM开发代码,开发中的朋友可以看一下它的代码。再次感谢IceskYsl的工作。

前两部分的内容先到这里,下一篇介绍其他的资料,包括OpenFire服务器的搭建和如何使用QQ实现Jabber客户端功能。


  • 2016年目标:工作拿出成绩,写知乎专栏,写自习室公众号,写《Rails 实践》第二版。

  • hi,我是里克,这是我的技术博客,从2007年开始,我在这里记录工作中的点点滴滴,同时,它也让我认识了很多的朋友。我相信,『坚持』就会有好运。

  • 我的邮箱:hi(at)liwei.me

  • 《Rails 实践》rails-practice.com

  • 简书主页

  • 知乎主页

公众号
Tags
rss