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
先粗算,好比把經緯度差一以上的全去掉,where latitude>y-1 and latitude<y+1 and longitude>x-1 and longitude <x+1 and ... ; x,y爲當前用戶的經緯度。
再小範圍概算,使用相似這樣的公式 order by abs(longitude -x)+abs(latitude -y) limit 100;
最後顯示時再精確計算 使用相似這樣的公式:(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>
以上兩種思路的優缺點:
XEP 0080 : 官方擴展協議,比較通用,也更加符合LBS是一種特殊的message的理念; 可是可定製性不強,不能增長本身的不少業務邏輯,尤爲是「附近的人」功能並不包含;
增長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