在XMPP的JAVA开源实现Openfire中,增长LBS 附近的人功能

1. XMPP协议 与 Openfirehtml

XMPP协议是IM领域的标准协议了,具体可参考  http://xmpp.org   及RFC6120,RFC6121,RFC6122等相关文档。 http://xmpp.org/xmpp-protocols/   node

XMPP协议实现,开源的也不少,server端可参考 http://xmpp.org/xmpp-software/servers/    client能够参考 http://xmpp.org/xmpp-software/clients/    library等可参考 http://xmpp.org/xmpp-software/libraries/    git

其中XMPP协议的JAVA实现 Openfire 热门程度很高,也许取决于其安装使用门槛低以及底层基于MINA框架的经典实现等优点。github

http://igniterealtime.org/projects/openfire 算法

 

2. LBS之附近的人 数据库

在移动设备上,几乎大多数的IM类应用都有“附近的人”功能,其原理也很是简单,每个用户若要查看本身附近的其余用户,则须上传本身的地理位置(GPS,基站定位)以共享;服务器

server端则经过计算地球上两点距离来推送必定半径内的其余用户信息给使用者。框架

 

具体算法实现,咱们参考你们通用的作法,好比来自zhihu上同行的分享:dom

用经纬度作索引,ide

  1. 先粗算,好比把经纬度差一以上的全去掉,where latitude>y-1 and latitude<y+1 and longitude>x-1 and longitude <x+1 and ... ; x,y为当前用户的经纬度。

  2. 再小范围概算,使用相似这样的公式 order by abs(longitude -x)+abs(latitude -y) limit 100;

  3. 最后显示时再精确计算 使用相似这样的公式:(2 * 6378.137* ASIN(SQRT(POW(SIN(PI()*(y-lat)/360),2)+COS(PI()*x/180)* COS(lat * PI()/180)*POW(SIN(PI()*(x-lng)/360),2))))。

前两项在数据库端计算,后一项在应用服务器端计算便可。

3. XMPP协议扩展

若是要在XMPP协议上增长LBS功能,那么须要咱们扩展XMPP,增长新的请求和响应报文。

目前有两种思路来扩展 XMPP,一种是官方的扩展,见XEP0080   http://xmpp.org/extensions/xep-0080.html ,就是在message中增长LBS信息;

 

Example 1. Entity publishes location

<iq type='set' from='portia@merchantofvenice.lit/pda' id='publish1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <publish node='http://jabber.org/protocol/geoloc'>
      <item>
        <geoloc xmlns='http://jabber.org/protocol/geoloc' xml:lang='en'>
          <accuracy>20</accuracy>
          <country>Italy</country>
          <lat>45.44</lat>
          <locality>Venice</locality>
          <lon>12.33</lon>
        </geoloc>
      </item>
    </publish>
  </pubsub>
</iq>
   

Example 2. Subscriber receives event with payload

<message from='portia@merchantofvenice.lit' 
         to='bassanio@merchantofvenice.lit'>
  <event xmlns='http://jabber.org/protocol/pubsub#event'>
    <items node='http://jabber.org/protocol/geoloc'>
      <item id='d81a52b8-0f9c-11dc-9bc8-001143d5d5db'>
        <geoloc xmlns='http://jabber.org/protocol/geoloc' xml:lang='en'>
          <accuracy>20</accuracy>
          <country>Italy</country>
          <lat>45.44</lat>
          <locality>Venice</locality>
          <lon>12.33</lon>
        </geoloc>
      </item>
    </items>
  </event>
</message>
   

 

另外一种思路是经过添加自定义的IQ指令来实现,好比咱们设计以下:

REQUEST

<iq id="c919" type="get" from="chris@im.nodexy.com/TCL-S960">
<query xmlns="com.nodexy.im.openfire.location">
    <item user="chris" lon="22.323009" lat="29.098763"/>
</query>

注意:

默认iq不设置to属性,则表示发送给 openfire server ,即to=im.nodexy.com ;

若是user a但愿将本身的地理位置信息共享发送给好友user b,则须要显式设置to=userb@domain  ;此时server只会转发此IQ消息不会作其余处理。

 

RESPONSE

<iq id="c919" type="result" from="chris@im.nodexy.com/TCL-S960">
<query xmlns="com.nodexy.im.openfire.location">
    <item user="chris1" lon="22.323009" lat="29.098763" sex="0" online="30min"/>
    <item user="chris2" lon="22.323009" lat="29.098763" sex="0" online="30min"/>
    <item user="chris3" lon="22.323009" lat="29.098763" sex="0" online="30min"/>
    ... ...
</query>

 

以上两种思路的优缺点:

  1. XEP 0080 : 官方扩展协议,比较通用,也更加符合LBS是一种特殊的message的理念; 可是可定制性不强,不能增长本身的不少业务逻辑,尤为是“附近的人”功能并不包含;

  2. 增长IQ指令: 更加灵活,按需使用,支持“附近的人”甚至“附近的商家”等;固然缺点就是不通用,属于私有协议,以私有插件形式实现。

     

本文咱们主要采用第二种。

 

4. Openfire插件实现 

在Openfire中实现LBS功能,能够采用开发新插件的方式来实现上面的扩展协议。

关于openfire插件开发可参考  http://www.igniterealtime.org/builds/openfire/docs/latest/documentation/plugin-dev-guide.html 

 

5. 代码分享

笔者这里分享一个基础版本的OpenfireLBS插件   https://github.com/node/openfireLBS  

相关文章
相关标签/搜索