共计 3691 个字符,预计需要花费 10 分钟才能阅读完成。
摘要
小编是个写了几年 php
的码农,接触纯 Js 的项目这也是头一次,另外,IM 的服务端是 Java(tigase 框架),为了解决旧版本 BOSH(长轮询)即时消息不稳定问题,决定更换 pc 网页版为 websockt 链接, App 用 socket 直连,特此更新服务端到 8.0,更新安装期间遇到了不少坑,再次记录,熟练 IM 或者 xmpp 协议用法的不用继续看了。
怎么添加账户,测试是否成功等工具方法见另一篇
传送门
基础语法
xmpp 寻址和节,另一篇基础 [应用层协议之 xmpp 基础学习](https://segmentfault.com/a/1190000019319742)
xmpp 主要是以 xml 格式传输数据,详细请看 xep 协议,这里用 strophe 的构建器,主要用到的如下:$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,详细的状态码参考源码:
关于 ssl 认证的问题,暂时采取 plain 方式,后续更新其他方式,比如:sha1。
单聊
- 发送 demo
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。
最简单的 demo:
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);
});
});
成功后返回以下信息:
<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, 示例代码见《插件使用方法》。
群聊
群聊相对单聊要复杂的多,首先是入群(这里的群没有密码),出席,发消息。
- 出席
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》第三部分十四章。
栽过的坑
- addHandlers 转 handlers 的时候回调函数丢失.
参考文献
- XMPP 高级编程 + 使用 JavaScript 和 jQuery
正文完
发表至: javascript
2019-07-12