Javascript、Websockets 和 XMPP 客户端。如何让它们协同工作?
Javascript, Websockets and XMPP client. How to make them work together?
我需要一个 "Hello world!" 示例,演示如何组合使用 websocket
和 ejabberd
。所以,这就是我所在的位置:
- 我安装了
ejabberd
并且 运行正在安装
- 我有两个帐户:"user1" 和 "user2",密码为“123”
- 我可以运行
psi plus
两个用户下的客户端,我可以发送
给我自己留言
- 我从
ejabberd
的官方网站知道它支持websockets
- 我知道有很多人使用的流行插件
Strophe.js
连接到 ejabberd
这是问题列表:
- 我不知道设置
ejabberd
配置的正确方法是什么
(我想,我安装了新版本的 ejabberd 及其
配置位于ejabberd.yml
)
- 不知道要不要做具体配置
Apache
服务器(代理、重写等 - 在许多论坛中
我见过一些涉及此类操作的示例)
- 我不知道
Javascript
或 C++
或 Python
代码会怎样
匹配这个拼图,这样我就可以做一个简单的
connect
或 send
一条消息
好吧,我花了两天时间,完全白费了。无论我有什么配置设置,无论我有什么代码,我总是从 FF 得到一条消息:
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
我想,我尝试了几十 * 几十种组合,但其中 none 行得通。所以,我需要一个分步说明来回答这三个问题:
- 如何设置
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: {}
如果 documentation 没有撒谎,我认为这应该有效。但是,在这种情况下,我无法重新启动 ejabberd
,现在在其日志文件中我看到了这条消息:
initialization was aborted because a module start failed
套餐
这是关于 ejabberd
软件包的一些信息,我使用以下命令简单地安装了它:
$ apt-get -y install ejabberd
所以,$ dpkg -s ejabberd
returns
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
returns
● 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 添加
request_handlers:
"/http-ws": ejabberd_http_ws
这将在 5280 端口可用:/http-ws
如果这不方便,您可以使用apache 或nginx 从端口80 进行代理。
对于 nginx,在虚拟主机中你需要这样的东西,其中 JABBERIP 是 ejabberd 的 ip 地址。这代理了从标准 http 端口 80 到 ejabberd 的 websocket 连接,连接配置为处理 websockets。
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.yml 中的 websocket 设置 - 我将它们放在文件的顶部..
websocket_ping_interval: 60
websocket_timeout: 86400
设置 strophe 超出了本答案的范围,但关键是设置连接以使用 websockets(如果浏览器支持的话)。以下代码片段来自 angularjs 应用程序 - 尽管您明白了...SocketUrl 是 /http-ws 位置的 public 位置,如上所示。这可能是 :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 库 - 但如果您正在考虑在网络浏览器中为 运行 构建应用程序,strophe 是一个很好的选择。
我需要一个 "Hello world!" 示例,演示如何组合使用 websocket
和 ejabberd
。所以,这就是我所在的位置:
- 我安装了
ejabberd
并且 运行正在安装 - 我有两个帐户:"user1" 和 "user2",密码为“123”
- 我可以运行
psi plus
两个用户下的客户端,我可以发送 给我自己留言 - 我从
ejabberd
的官方网站知道它支持websockets
- 我知道有很多人使用的流行插件
Strophe.js
连接到ejabberd
这是问题列表:
- 我不知道设置
ejabberd
配置的正确方法是什么 (我想,我安装了新版本的 ejabberd 及其 配置位于ejabberd.yml
) - 不知道要不要做具体配置
Apache
服务器(代理、重写等 - 在许多论坛中 我见过一些涉及此类操作的示例) - 我不知道
Javascript
或C++
或Python
代码会怎样 匹配这个拼图,这样我就可以做一个简单的connect
或send
一条消息
好吧,我花了两天时间,完全白费了。无论我有什么配置设置,无论我有什么代码,我总是从 FF 得到一条消息:
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
我想,我尝试了几十 * 几十种组合,但其中 none 行得通。所以,我需要一个分步说明来回答这三个问题:
- 如何设置
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: {}
如果 documentation 没有撒谎,我认为这应该有效。但是,在这种情况下,我无法重新启动 ejabberd
,现在在其日志文件中我看到了这条消息:
initialization was aborted because a module start failed
套餐
这是关于 ejabberd
软件包的一些信息,我使用以下命令简单地安装了它:
$ apt-get -y install ejabberd
所以,$ dpkg -s ejabberd
returns
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
returns
● 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 添加
request_handlers:
"/http-ws": ejabberd_http_ws
这将在 5280 端口可用:/http-ws
如果这不方便,您可以使用apache 或nginx 从端口80 进行代理。
对于 nginx,在虚拟主机中你需要这样的东西,其中 JABBERIP 是 ejabberd 的 ip 地址。这代理了从标准 http 端口 80 到 ejabberd 的 websocket 连接,连接配置为处理 websockets。
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.yml 中的 websocket 设置 - 我将它们放在文件的顶部..
websocket_ping_interval: 60
websocket_timeout: 86400
设置 strophe 超出了本答案的范围,但关键是设置连接以使用 websockets(如果浏览器支持的话)。以下代码片段来自 angularjs 应用程序 - 尽管您明白了...SocketUrl 是 /http-ws 位置的 public 位置,如上所示。这可能是 :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 库 - 但如果您正在考虑在网络浏览器中为 运行 构建应用程序,strophe 是一个很好的选择。