我需要一个"Hello world!"示例,演示如何组合使用websocket
s和ejabberd
。所以,这就是我的位置:
- 我已经安装并运行
ejabberd
- 我有两个帐户:"user1"one_answers"user2",密码为"123"
- 我可以在两个用户下运行
psi plus
客户端,我可以发送给自己的信息 - 我从
ejabberd
的官方网站知道它支持websockets
我知道有一个很流行的插件
Strophe.js
,很多人都在用连接ejabberd
,这是问题列表:
- 我不知道设置
ejabberd
配置的正确方法是什么(我猜,我安装了ejabberd和它的新版本配置位于ejabberd.yml
) - 我不知道我是否应该做具体的配置
Apache
服务器(代理,重写等)在许多论坛我已经看到了一些涉及到这样的操作的例子) - 我不知道
Javascript
或C++
或Python
代码是什么搭配这个谜题,这样我就可以做一个简单的connect
to或send
a message
Firefox can't establish connection to the server
at ws://localhost:5280/http-ws
是的,我编辑了ejabberd.yml
,所以它有这些行:
requests_handlers:
"http-ws/": ejabberd_http_ws
我也编辑了apache的配置,所以我有:
ProxyRequests off
ProxyPass /http-ws/ http://localhost:5280/http-ws/
ProxyPassReverse /http-ws/ http://localhost:5280/http-ws/
RewriteEngine on
RewriteRule http-ws/ http://localhost:5280/http-ws/
确实,我重新启动了apache和ejabberd。在我的代码中,我有:
var SocketUrl = 'ws://localhost:5280/http-ws'
...other standard stuff
我想,我尝试了几十*几十种组合,但没有一种有效。所以,我需要一个分步指导来回答这三个问题:
- 如何设置
ejabberd
- 如何设置
Apache
- 如何原始的例子(在
JavaScript
)应该看起来像
编辑
我现在的配置:
1. ejabberd.yml:
...
hosts:
- "localhost"
....
listen:
....
-
port: 5280
ip: "::"
module: ejabberd_http
request_handlers:
"/http-ws": ejabberd_http_ws
web_admin: true
http_poll: true
http_bind: true
....
acl:
admin:
user:
- "admin": "localhost"
access:
configure:
admin: allow
2. apache2.conf
<Directory />
AllowOverride All
Allow From All
</Directory>
<Directory /var/www/site>
AllowOverride All
Allow From All
</Directory>
3. apache2/sites-available/000-default.conf
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/site
<Directory /var/www/site>
Options +Indexes +MultiViews
</Directory>
ProxyRequests off
AddDefaultCharset UTF-8
ProxyPass /http-ws/ http://127.0.0.1:5280/http-ws/
ProxyPassReverse /http-ws/ http://127.0.0.1:5280/http-ws/
RewriteEngine on
RewriteRule /http-ws/http://127.0.0.1:5280/http-ws/
...
最后这是我的代码:
window.onload = function(){
var SocketUrl = 'ws://localhost:5280/http-ws/';
var connection = null;
function onConnect(status){
if (status == Strophe.Status.CONNECTING) {
alert('Strophe is connecting.');
} else if (status == Strophe.Status.CONNFAIL) {
alert('Strophe failed to connect.');
} else if (status == Strophe.Status.DISCONNECTING) {
alert('Strophe is disconnecting.');
} else if (status == Strophe.Status.DISCONNECTED) {
alert('Strophe is disconnected.');
} else if (status == Strophe.Status.CONNECTED) {
alert('Strophe is connected.');
}
}
var button = document.getElementById("connect");
button.onclick = function(){
connection = new Strophe.Connection(SocketUrl);
var jid = document.getElementById("jid").value;
var pass = document.getElementById("pass").value;
connection.connect(jid, pass, onConnect);
}
}
因此,在运行这个示例时,我总是得到这些警告:
Strophe is connecting
Strophe failed to connect
Strophe is disconnected
在控制台中,我看到这个错误消息:
Firefox can't establish a connection to the server at ws://localhost:5280/http-ws/
Ejabberd日志
这是我在ejabberd
日志中的内容:
2015-08-20 12:52:40.558 [error] <0.448.0> CRASH REPORT Process <0.448.0> with 0 neighbours crashed with reason: call to undefined function ejabberd_http_ws:process([], {request,'GET',[<<"http-ws">>],[{nokey,<<>>}],{<<>>,<<>>},undefined,<<"en-US">>,<<>>,{{0,0,0,0,...},...},...})
2015-08-20 12:52:40.559 [error] <0.326.0> Supervisor ejabberd_http_sup had child undefined started with {ejabberd_http,start_link,undefined} at <0.448.0> exit with reason undef in context child_terminated
我想,我应该强调日志中的这一行:
call to undefined function ejabberd_http_ws
我试图在ejabberd.yml
中启用module
节下的此模块,如:
modules:
...
mod_http_ws: {}
我认为应该有效,如果文档没有说谎的话。然而,在这种情况下,我无法重新启动ejabberd
,在它的日志文件中,我现在看到这个消息:
initialization was aborted because a module start failed
包这是一些关于ejabberd
包的信息,我只是用命令安装:
$ apt-get -y install ejabberd
那么,$ dpkg -s ejabberd
返回
Package: ejabberd
Status: install ok installed
Priority: optional
Section: net
Installed-Size: 6405
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Architecture: amd64
Version: 14.07-4ubuntu1
Provides: xmpp-server
Depends: adduser, erlang-base (>= 1:15.b) | erlang-abi-17.0, erlang-asn1 (>= 1:17.3-dfsg), erlang-base (>= 1:17.3-dfsg) | erlang-base-hipe (>= 1:17.3-dfsg), erlang-crypto (>= 1:17.3-dfsg), erlang-inets (>= 1:17.3-dfsg), erlang-mnesia (>= 1:17.3-dfsg), erlang-odbc (>= 1:17.3-dfsg), erlang-public-key (>= 1:17.3-dfsg), erlang-ssl (>= 1:17.3-dfsg), erlang-syntax-tools (>= 1:17.3-dfsg), openssl, ucf, debconf (>= 0.5) | debconf-2.0, erlang-lager, erlang-jiffy, erlang-p1-cache-tab, erlang-p1-iconv, erlang-p1-mysql, erlang-p1-pam, erlang-p1-pgsql, erlang-p1-sip, erlang-p1-stringprep, erlang-p1-stun, erlang-p1-tls, erlang-p1-utils, erlang-p1-xml, erlang-p1-yaml, erlang-p1-zlib, erlang-xmlrpc
Recommends: ejabberd-contrib
Suggests: libunix-syslog-perl, imagemagick | graphicsmagick-imagemagick- compat
Conflicts: ejabberd-mod-shared-roster-ldap
Conffiles:
/etc/default/ejabberd 49352468a39da545ad13586af05877f9
/etc/ejabberd/inetrc a8de3c20d2ac990c8f319907b340d6a2
/etc/init.d/ejabberd 58aa53c895ae2250e80ea16769db0417
/etc/logrotate.d/ejabberd d2a0a63e544aabfb797f718471c6d173
/etc/ufw/applications.d/ejabberd abc263fcde39ff65e9b5722be81db8ff
Description: distributed, fault-tolerant Jabber/XMPP server written in Erlang
ejabberd is a distributed, fault-tolerant Jabber/XMPP server written in Erlang.
和$ service ejabberd status
返回
● ejabberd.service - LSB: Starts ejabberd jabber server
Loaded: loaded (/etc/init.d/ejabberd)
Active: active (exited) since Thu 2015-08-20 13:32:27 PDT; 12h ago
Docs: man:systemd-sysv-generator(8)
Process: 12701 ExecStop=/etc/init.d/ejabberd stop (code=exited, status=0/SUCCESS)
Process: 13716 ExecStart=/etc/init.d/ejabberd start (code=exited, status=0/SUCCESS)
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 156: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 157: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 158: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 159: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 160: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 161: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 163: /etc/eja...d
Aug 20 13:32:22 ubuntu ejabberd[13716]: /usr/sbin/ejabberdctl: 164: /etc/eja...d
Aug 20 13:32:27 ubuntu ejabberd[13716]: done.
Aug 20 13:32:27 ubuntu systemd[1]: Started LSB: Starts ejabberd jabber server.
Ejabberd从15.03版本开始支持websockets -这解决了上面的答案。
这与python或c++无关——这个难题只是关于配置Ejabberd来支持websockets,并选择使用代理来处理websockets流量。
在ejabjjerd下面。Yml节,模块:ejabberd_http add
request_handlers:
"/http-ws": ejabberd_http_ws
这将在端口5280可用:/http-ws
如果不方便,您可以使用apache或nginx从80端口代理。
对于nginx,在虚拟主机中,您需要这样做,其中JABBERIP是ejabberd的ip地址。这将代理从标准http端口80到ejabberd的websocket连接,该连接配置为处理websocket。
location /http-ws/ {
proxy_pass http://JABBERIP:5280; // this is
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
你可能还需要调整ejabberd中的websocket设置。我把这些放在文件的顶部..
websocket_ping_interval: 60
websocket_timeout: 86400
设置strophe超出了这个答案的范围,但关键的一点是设置连接使用websockets,如果浏览器支持这一点。下面的代码片段来自于一个angularjs应用——不过你应该明白了……SocketUrl是如上所示的/http-ws位置的公共位置。这可能是:5280版本或代理到端口80的版本。
if (window.WebSocket && (passwd != 'undefined' && passwd != null)) {
$this.connection = new Strophe.Connection($this.SocketUrl);
$this.connection.connect(user_info.username+'@'+$this.jabberUrl, passwd, $this.onConnect.bind($this));
} else {
UserService.getJabberData().then(function (response) {
var jabber = response.data;
$this.connection = new Strophe.Connection($this.BOSHUrl);
$this.connection.attach(jabber.jid, jabber.sid, jabber.rid, $this.onConnect.bind($this));
});
}
也有用于python和其他语言的xmpp库-尽管如果你正在考虑构建一个在web浏览器中运行的应用程序,strophe是一个很好的选择。