使用Strophe连接xmpp,轻松构建web即时聊天工具。
转载:https://blog.csdn.net/e421083458/article/details/38081419
实现原理
实现webim方法有很多,最关键的问题是保持和服务端的连接。如何保障会话的即时性和连通性。常用的有poll, long poll, comet等;; 其中poll的方式效果最差,一般都会有1到2秒的延迟。long poll和comet技术比较新,因为http无状态的原因,这种长连接方式要保持,一般都需要服务端额外代码提供支持。像gtalk采用的就是long poll的方式。服务端常会使用异步IO等方式来支持高并发。
本文使用的是XEP标准扩展规范,XEP-0124 提供的方法实现WebIM. 思路即使用一个javascript的xep-0124的实现,直接连接xmpp server端。目前xep-0124的实现,在大部分的xmpp server实现中都支持,本文使用的是OpenFire 3.6.4 作为Xmpp Server。
XEP 0124规范定义了一个比较完整和安全的协议,具体请参阅相当文档。本文使用javascript端的XEP-0124的实现为Strophe的js实现。
另外因为浏览器javascript跨域问题,需要使webim里调用javascript也是80端口,并同一子域,所以使用Apache或者Nginx 在80端口,并转发/http-bind请求至Xmpp Server的http-binding端口。本机使用Nginx. xmpp server 使用使用7070端口。
一、安装openfire:http://blog.csdn.net/e421083458/article/details/38037373
二、配置apache
我们下载安装的是httpd-2.2.17-win32-x86-no_ssl.msi,安装完成后,我们需要配置一下,由于jwchat是用javacript去和openfire进行通讯的,所以他们之间的通讯是基于http的,但是由于浏览器为了安全性是不允许javascript跨域访问的。我们必须通过别的技术来绕过这限制,所以我们采取apache服务器的重定向功能去突破这个限制。
安装完成后进入到apache的安装目找到conf文件夹下的httpd.conf文件,用记事本打开,把下列几个配置项放开(默认被注释掉了)
1、LoadModule rewrite_module modules/mod_rewrite.so
2、LoadModule proxy_module modules/mod_proxy.so
3、LoadModule proxy_http_module modules/mod_proxy_http.so
然后再在本配置文件的末尾加入如下几行配置
ServerName blzc.com
<Directory /var/jwchat>
Options +Indexes +MultiViews
</Directory>
AddDefaultCharset UTF-8
RewriteEngine on
ProxyPass /jwchat/http-bind/ http://blzc.com:7070/http-bind/
在此有必要对proxyPass的参数做些说明
“/jwchat/http-bind/”:jwchat就通过访问http://域名/jwchat/http-bind/地址去和openfire通讯,apache接到请求后就会重新定向到http://blzc.com:7070/http-bind/
“http://blzc.com:7070/http-bind/”:被重新定向的地址,也就是我们的openfire的http访问地址。7070端口是openfire的默认访问端口,当然我们也可以进入openfire进行配置。
三、openfire的配置
安装好openfire后进入web式的管理界面,选择服务器-》服务器管理器-》系统属性
在里边添加两个属性(记得选择不加密)
xmpp.httpbind.client.requests.polling = 0
xmpp.httpbind.client.requests.wait = 10
四、创建聊天脚本
创建index.html页面:
html 1行
-
<!DOCTYPE html>
-
<html>
-
<head>
-
<title>Latest content</title>
-
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
-
<script type="text/javascript"
-
src="strophejs/strophe.js"></script>
-
<script type="text/javascript"
-
src="pingstream.js"></script>
-
</head>
-
<body>
-
<div id='login' style='text-align: left'>
-
<form name='cred'>
-
<label for='jid'>JID:</label>
-
<input type='text' id='jid' value="richard@csdn.shimiso.com" /><br/>
-
<label for='pass'>Password:</label>
-
<input type='password' id='pass' value="niuyufu123" /><br/>
-
<input type='button' id='connect' value='connect' />
-
</form>
-
</div>
-
<hr />
-
<div style="text-align: left">
-
<label for='tojid'>tojid</label>
-
<input type='text' id='tojid' value="" /><br/>
-
<label for='msg'>msg:</label>
-
<textarea id="msg">Hello world!!!</textarea>
-
<br/>
-
<input type='button' id='replay' value='replay' />
-
</div>
-
<hr />
-
<div id='log'></div>
-
</body>
-
</html>
创建pingstream.js
javascript 1行
-
var BOSH_SERVICE = '/http-bind/';
-
var connection = null;
-
function log(msg)
-
{
-
$('#log').append('<div></div>').append(document.createTextNode(msg));
-
}
-
/**
-
* 连接绑定方法
-
* @param status
-
*/
-
function onConnect(status)
-
{
-
if (status == Strophe.Status.CONNECTING) {
-
log('Strophe is connecting.');
-
} else if (status == Strophe.Status.CONNFAIL) {
-
log('Strophe failed to connect.');
-
$('#connect').get(0).value = 'connect';
-
} else if (status == Strophe.Status.DISCONNECTING) {
-
log('Strophe is disconnecting.');
-
} else if (status == Strophe.Status.DISCONNECTED) {
-
log('Strophe is disconnected.');
-
$('#connect').get(0).value = 'connect';
-
} else if (status == Strophe.Status.CONNECTED) {
-
log('Strophe is connected.');
-
log('ECHOBOT: Send a message to ' + connection.jid +
-
' to talk to me.');
-
connection.addHandler(onMessage, null, 'message', null, null, null);
-
connection.send($pres().tree());
-
}
-
}
-
/**
-
* 获取消息时的方法
-
* @param msg
-
* @returns {Boolean}
-
*/
-
function onMessage(msg) {
-
var to = msg.getAttribute('to');
-
var from = msg.getAttribute('from');
-
var type = msg.getAttribute('type');
-
var elems = msg.getElementsByTagName('body');
-
if (type == "chat" && elems.length > 0) {
-
var body = elems[0];
-
log('ECHOBOT: I got a message from ' + from + ': ' +
-
Strophe.getText(body));
-
/* 关闭echo机器的自动回复
-
var reply = $msg({to: from, from: to, type: 'chat'})
-
.cnode(Strophe.copyElement(body));
-
connection.send(reply.tree());
-
log('ECHOBOT: I sent ' + from + ': ' + Strophe.getText(body));*/
-
}
-
return true;
-
}
-
/**
-
* 发信息
-
* @param toId
-
* @param fromId
-
* @param msg
-
*/
-
function sendMsg(toId,fromId,msg) {
-
var reply = $msg({to: toId, from:fromId , type: 'chat'}).cnode(Strophe.xmlElement('body', '' ,msg));
-
connection.send(reply.tree());
-
log('ECHOBOT: I sent ' + toId + ': ' + msg);
-
}
-
/**
-
* 事件监听
-
*/
-
$(document).ready(function () {
-
connection = new Strophe.Connection(BOSH_SERVICE);
-
// Uncomment the following lines to spy on the wire traffic.
-
connection.rawInput = function (data) { console.log('RECV: ' + data); };
-
connection.rawOutput = function (data) { console.log('SEND: ' + data); };
-
// Uncomment the following line to see all the debug output.
-
//Strophe.log = function (level, msg) { log('LOG: ' + msg); };
-
$('#connect').bind('click', function () {
-
var button = $('#connect').get(0);
-
if (button.value == 'connect') {
-
button.value = 'disconnect';
-
connection.connect($('#jid').get(0).value,
-
$('#pass').get(0).value,
-
onConnect);
-
} else {
-
button.value = 'connect';
-
connection.disconnect();
-
}
-
});
-
$('#replay').bind('click', function () {
-
toId = $('#tojid').val();
-
fromId = $('#jid').val();
-
msg=$('#msg').val();
-
sendMsg(toId,fromId,msg);
-
});
-
});
用pandian与聊天页并行测试。
成功后的截图:
代码下载地址:http://download.csdn.net/detail/e421083458/7672297