使⽤strophe.js连接openfire服务器实现web端即时通讯
最近公司需要做⼀个简单的即时通讯功能,因为不是什么主要的功能板块,⽽且资⾦有限,所以要求要⽤开源的。之前⾃⼰⽤过环信还有极光,但是这两个都是要收费的。后⾯查了⼀段时间以后,选择⽤openfire作为服务端,strophe.js作为客户端来进⾏开发。主要实现了,⽂字、图⽚、视频、位置、⽂件发送,开发过程中遇到的问题还是蛮多的,这⾥就记录⼀下,以便以后参考!
服务器搭建好了以后,需要⼏个东西:
2,服务器名称:zhangyh
3,创建两个⽤户,⽤于后⾯进⾏聊天:admin和x5411
注意:⽤户创建这⾥有个⼩坑,不能⽤中⽂,不能⽤⼤写字母!
好了,现在服务端的东西都准备好了,剩下的就是客户端了,客户端这⾥,在选⽤strophe之前,试过converse.js和
websocket,converse的话,⽤起来倒是挺⽅便的,但是如果你要⾃定义你⾃⼰的界⾯,想⾃⼰把各个模块分离出来的话超级⿇烦,⽽且,它的开发⽂档,看起来只有那么了,直接pass掉。然后websocket的话,因为不是现成的,所有的包括连接,登录,发送,接收都要⾃⼰⼀步步的慢慢写,慢慢实现,⽤起来不是很⽅便。但是感觉如果想搞得好⼀点的话,使⽤websocket应该会好⼀点!最后,就选⽤了strophe。
开始客户端的开发:页⾯需要引⼊strophe.js,然后就可以开始了
<script type="text/javascript" src="cdn.bootcss/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="cdn.bootcss/strophe.js/1.1.3/strophe.min.js"></script>
1,连接openfire服务器,登录,注意:登录的⽤户名,后⾯需要拼上服务器的名称,如:admin@zhangyh
//登录openfire
function loginOpenfire() {
// 初始化strophe.js,获取当前账户的登录信息
let service = Constant.OPENFIRE_BOSH_SERVICE;//服务器地址
//刚才创建的⽤户的账号和密码
let userName = Constant.OPENFIRE_ACCOUNT_NAME;//admin@zhangyh
let passWord = Constant.OPENFIRE_ACCOUNT_PASSWORD;//admin@123
//开始登录,完成登录以后,会有个回调⽅法onConnect
onConnect(status)
});
}
/**
* 连接状态改变时触发
*/
function onConnect(status) {
if (status == Strophe.Status.CONNFAIL) {
alert("连接失败,⽹络异常!");
} else if (status == Strophe.Status.AUTHFAIL) {
alert("登录失败,账号或密码错误!");
} else if (status == Strophe.Status.DISCONNECTED) {
alert("连接断开了!");
//这⾥可以根据⾃⼰的业务逻辑来处理,要保持登录就调⽤登录⽅法
loginOpenFire();
} else if (status == Strophe.Status.CONNECTED) {
console.log("连接成功,可以开始聊天了!");
// 当接收到消息时,调⽤reMessage回调函数
connection.addHandler(function(msg){
reMessage(msg);
}, null, 'message', null, null, null);
// ⾸先要发送⼀个<presence>给服务器(initial presence),这⼀步必须做,要不然服务器不知道你到底要⼲嘛
connection.send($pres().tree());
}
}
2,发送聊天信息
/**
* 发送聊天信息
*/
function sendText() {
var val = "发送内容";//需要发送的⽂字内容
// 创建⼀个<message>元素并发送
var msg = $msg({
to: sendTo,//发送对象的⽤户名 x5411@zhangyh
from: jid,//发送⼈ admin@zhangyh
type: 'chat'
}).c("body", null, val);
connection.());
console.());
}
注意:这个地⽅,⽣成message树,创建body的时候,那个val如果是个字符串类型(⽂本内容),⽣成的body是这样的<body>⽂本内容</body>
如果val是个对象的话,就会⾃动把对象的key和value以属性的形式放进body⾥⾯
3,接收聊天信息
/**
* 收到消息
*/
function reMessage(msg) {
// 解析出<message>的from、type属性,以及body⼦元素
var from = Attribute('from');
var type = Attribute('type');
var elems = ElementsByTagName('body');
if (type == "chat" && elems.length > 0) {
var body = elems[0];前端websocket怎么用
alert("接收到的消息是:"+Text(body));
}
return true;
}
这⾥遇到个问题,我在写demo的时候,⽤的是原⽣的js写的,所以监听收到消息的触发,只需要在onConnect⽅法⾥⾯做⼀次就可以了,但是实际开发环境是⽤的react开发的,实际运⾏的时候接收消息的监听执⾏⼀次以后,后⾯就不会执⾏了,就导致正式聊天的时候第⼀次可以收到消息,后⾯就就接收不到了!百度到的⼀个⽐较接近的答案是,因为strophe.js⾥⾯在消息监听⾥⾯做了try{}catch{},然后正式环境⾥⾯进⾏消息监听的时候捕捉到了项⽬其它地⽅的异常信息,strophe以为消息监听异常没有完成,所以就销毁了这个监听(但是实际上是正常的)。感觉应该就是这个原因导致的,但是我把所有源码⾥⾯的异常捕捉都去掉了以后还是不⾏,所以就在每次监听完成接收到消息以后,再启⽤⼀次监听,这样即使上⼀个被销毁了,监听还是可以有效。
/**
* 收到消息
*/
function reMessage(msg) {
// 解析出<message>的from、type属性,以及body⼦元素
var from = Attribute('from');
var type = Attribute('type');
var elems = ElementsByTagName('body');
if (type == "chat" && elems.length > 0) {
var body = elems[0];
alert("接收到的消息是:"+Text(body));
}
//每次收到消息以后都要进⾏下⼀次监听,如果不做这⼀步,就只能监听⼀次(未解决)
connection.addHandler(function(msg){
reMessage(msg);
}, null, 'message', null, null, null);
return true;
}
上⾯就是⼀个简单的,登录、发送、接收的过程了!
然后问题⼜来了,strophe只⽤⽤于简单的⽂字聊天,涉及到⽂件的东西,需要借⽤到第三⽅的插件,XEP-0096: SI File Transfer,所以⼜去研究了⼀下⽂件传输的问题。研究了⼤半天,都没搞明⽩这东西是怎么传输的,光是⽂件传输的消息通知都没调通,⼀直报503(估计是我太菜了,有时间再继续研究下)。没办法,项⽬⼜催的⽐较急,只能另辟蹊径了!然后就想到了⼀个办法(这⾥不得不佩服⼀下我的机智了)。
这个办法是这样的,正常接收到的⽂字聊天信息是这样的<message><body>接收到消息了</body></message>,如果对⽅发送的是⼀个对象的话,⽐如 {name:123,type:456} ,那接收到的消息就是这样的<message><body name="123" type="456"></body>
</message>,所以,只要涉及到⽂件上传的,先将⽂件上传到我们⾃⼰的服务器上⾯,获取⽂件路径以后,将⽂件的所有信息以对象的形式发送给对⽅ ,对⽅接收到消息以后,根据body⾥⾯的type属性来区分发送⽅发送的是⽂字还是⽂件(图⽚,视频、位置同理)。
发送⽂件信息的完整过程:
1,选择⽂件
2,上传⽂件获取⽂件的完整路径、名称、⼤⼩等
3,将⽂件的信息封装成⼀个对象以⽂字的形式发送给接收⽅
4,这个时候接收⽅接收到消息以后,就可以进⾏解析,根据⽂件类型来进⾏展⽰
strophe和openfire这个东西实在太⽼了,⽹上描述倒是挺多的,但是真正开发的实例太少了,遇到问题都得⾃⼰慢慢摸索。过程虽然很坎坷,但是总算是搞完了!欢迎交流,⼀起进步!如果有什么说的不对的,欢迎指出哈!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论