Javascript、Websockets 和 XMPP 客户端。如何让它们协同工作?

标签 javascript websocket xmpp ejabberd

我需要一个“Hello world!”例如,它演示了如何结合使用 websocketejabberd。所以,这就是我所在的位置:

  1. 我安装并运行了 ejabberd
  2. 我有两个帐户:“user1”和“user2”,密码为“123”
  3. 我可以在两个用户下运行 psi plus 客户端并且我可以发送 给自己的留言
  4. 我从ejabberd 的官方网站知道它支持websockets
  5. 我知道有很多人使用的流行插件 Strophe.js 连接到 ejabberd

这是问题列表:

  1. 我不知道设置ejabberd 配置的正确方法是什么 (我想,我安装了新版本的 ejabberd 及其 配置位于 ejabberd.yml)
  2. 不知道要不要做具体的配置 Apache 服务器(代理、重写等 - 在许多论坛中 我见过一些涉及此类操作的示例)
  3. 我不知道 JavascriptC++Python 代码会怎样 匹配这个拼图,这样我就可以做一个简单的 连接发送消息

好吧,我花了两天时间,完全白费了。无论我有什么配置设置,无论我有什么代码,我总是从 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

我想,我尝试了几十 * 几十种组合,但没有一个有效。所以,我需要一个分步说明来回答这三个问题:

  1. 如何设置ejabberd
  2. 如何设置Apache
  3. 原始示例(在 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.ymlmodule 部分下启用此模块,例如:

modules:
   ...
   mod_http_ws: {}

如果documentation,我认为应该可以。没有说谎。但是,在这种情况下,我无法重新启动 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添加

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 是一个很好的选择。

关于Javascript、Websockets 和 XMPP 客户端。如何让它们协同工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32070678/

相关文章:

javascript - 开 Jest 单元测试 - 未找到测试

javascript - 继续计算两个数字之间的差异

amazon-web-services - 如何为 WebSocket 协议(protocol)配置 AWS ELB 和 Nginx?

java - Flash WebSockets 后备和 Jetty 8?

login - 使用 XMPP 时,如何检测用户 (JID) 是否已在登录时登录?

java - 无法通过 Smack API 使用 openfire 服务器发送/接收消息

javascript - 如何更新具有相同父值的同一级别中的所有现有元素?

javascript - 当我更改 .js 文件时 Visual Studio 崩溃

javascript - 是否可以使用 websocket 传输数据

ios - XMPPFramework 与 Openfire 的 TLS/SSL 连接