小编是个写了几年php
的码农, 接触纯Js的项目这也是头一次,另外,IM的服务端是Java(tigase框架) ,为了解决旧版本BOSH(长轮询)即时消息不稳定问题,决定更换pc网页版为websockt连接, App用socket直连,特此更新服务端到8.0,更新安装期间遇到了很多坑,再次记录,熟练IM或者xmpp协议用法的不用继续看了。javascript
怎么添加帐户,测试是否成功等工具方法见另外一篇php
传送门
xmpp寻址和节,另外一篇基础 应用层协议之xmpp基础学习
xmpp主要是以xml格式传输数据,详细请看xep协议,这里用strophe的构建器,主要用到的以下:html
$iq,info query,主要用来查询服务器信息,解析的最终结果是<iq></iq>。 $pres,解析的最终结果是<presence></presence>,上下线通知。 $msg, 解析的结果是<message></message>,同时能够经过.up()和.c()构建xml父子级别元素。
im.connect = new Strophe.Connection("ws://localhost:5290/xmpp-websocket/"); im.connect.connect('jid@localhost','pass',function(){ console.info('this is login callback.'); });
这里,服务端实际上是分为两步走,第一步是链接,链接成功后会返回状态码1,而后是登录,登录成功后返回状态5,详细的状态码参考源码:
关于密码认证的问题,暂时采起plain方式,后续更新其余方式,好比:sha1。java
var msg = $msg({ to: receiver, from: 'jid@localhost', type: 'one', name: 'zeronlee', photo: 'image.png' }).c("body", null,msg); im.connect.send(msg.tree());
查询归档以前,首先是要确保归档(存库)成功,服务端查看【传送门】,自行处理,参见XEP-0136: Message Archiving。node
最简单的demo:webpack
var iq = $iq({type: 'set'}).c('query', {xmlns: 'urn:xmpp:mam:1'}); im.connect.sendIQ(iq, function(a){ console.log('sent iq',a); $(a).find('item').each(function(){ var jid = $(this).attr('jid'); // jid console.log('jid',jid); }); });
成功后返回如下信息:git
<iq xmlns="jabber:client" to="im7857@localhost" id="d8a7cd10-16dd-43ae-ace2-20089713c920:sendIQ" type="result"> <fin xmlns="urn:xmpp:mam:1" complete="true"> <set xmlns="http://jabber.org/protocol/rsm"> <first index="0">nAhOrNd/DNXBFtivwbm/vrN8I4GL2SLkc76eNmN0ruw=</first> <last>cnosUN6U9Md6o8TvLD42rB6jJnfPKF2DxkEBFmuK/IQ=</last> <count>14</count> </set> </fin> </iq>
代表查出了14条历史消息,查询归档更多见XEP-0313: Message Archive Management,示例代码见《插件使用方法》。github
群聊相对单聊要复杂的多,首先是入群(这里的群没有密码),出席,发消息。web
var presence = $pres({from:'im7858@localhost',to:'6043@muc.localhost'}).c('x', {xmlns: 'http://jabber.org/protocol/muc'}).c('history', {maxstanzas: 0, maxchars:0, seconds:0}); im.connect.send(presence, function(a){ console.log('sent presence',a); });
var presence = $iq({from:'im7858@localhost@muc.localhost'}).c('query', {xmlns: 'http://jabber.org/protocol/disco#items'}); im.connect.send(presence, function(a){ console.log('sent presence',a); });
mam归档查询demo编程
/* XEP-0313: Message Archive Management * Copyright (C) 2012 Kim Alvefur * * This file is MIT/X11 licensed. Please see the * LICENSE.txt file in the source package for more information. * * Modified by: Chris Tunbridge (github.com/Destreyf/) * Updated to support v0.3 of the XMPP XEP-0313 standard * http://xmpp.org/extensions/xep-0313.html * */ Strophe.addConnectionPlugin('mam', { _c: null, _p: [ 'with', 'start', 'end' ], init: function (conn) { this._c = conn; Strophe.addNamespace('MAM', 'urn:xmpp:mam:1'); }, query: function (jid, options) { var _p = this._p; var attr = { type:'set', from:jid }; options = options || {}; var mamAttr = {xmlns: Strophe.NS.MAM, with:jid}; if (!!options.queryid) { mamAttr.queryid = options.queryid; delete options.queryid; } var iq = $iq(attr).c('query', mamAttr); // var i; // for (i = 0; i < this._p.length; i++) { // var pn = _p[i]; // var p = options[pn]; // delete options[pn]; // if (!!p) { // iq.c('field',{var:pn}).c('value').t(p).up().up(); // } // } // iq.up(); // var onMessage = options.onMessage; delete options.onMessage; var onComplete = options.onComplete; delete options.onComplete; //////////////////////////////////////////////// // iq.cnode(new Strophe.RSM(options).toXML()); var _c = this._c; var handler = _c.addHandler(onMessage, null, 'message', null); return this._c.sendIQ(iq, function (a) { console.log(a); _c.deleteHandler(handler); onComplete.apply(this, arguments); }, function (err) { //error callBack function console.log("Error Response from server:", err); }); } });
插件必须是Strophe.addConnectionPlugin('mam', {init:function(){}})
结构才得以成功加载,用webpack或者页面加载进来以后自动实例化init,群聊就是以插件形式使用,固然还能够自定义其余更高级的,具体参考《XMPP高级编程+使用JavaScript和jQuery》第三部分十四章。