首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在同一个端口上提供Cramp::Websocket和普通的Rack应用程序?

如何在同一个端口上提供Cramp::Websocket和普通的Rack应用程序?
EN

Stack Overflow用户
提问于 2012-05-05 20:21:28
回答 1查看 937关注 0票数 3

我试图使用相同的端口来提供正常的HTTP流量,以及使用Ruby1.9.3和HTML5 1.3.1通过抽筋 (构建在EventMachine之上)的抽筋 websocket。下面是一个最小的、独立的示例:

代码语言:javascript
复制
require 'thin'
require 'cramp'
require 'http_router'

Cramp::Websocket.backend = :thin

class SocketApp < Cramp::Action
  self.transport = :websocket

  on_start = :connected
  on_finish = :disconnected
  on_data = :message

  def connected
    puts 'Client connected'
  end
  def disconnected
    puts 'Client disconnected'
  end
  def message(msg)
    puts "Got message: #{msg}"
    render 'Here is your reply'
  end
end

class WebApp
  def call(env)
    [ 200, { 'Content-Type' => 'text/html' }, <<EOF
<html><head>
<script>
  function init() {
    function log(msg) { document.getElementById('log').innerHTML += msg + '<br>'; }
    var socketUri = 'ws://' + document.location.host + '/socket';
    log('Socket URI: ' + socketUri);
    var socket = new WebSocket(socketUri);
    socket.onopen = function(e) {
      log('onopen');
      socket.send('Is there anybody out there?');
      log('sent message');
    };
    socket.onclose = function(e) {
      log('onclose; code = ' + e.code + ', reason = ' + e.reason);
    };
    socket.onerror = function(e) {
      log('onerror');
    };
    socket.onmessage = function(e) {
      log('onmessage; data = ' + e.data);
    };
  }
</script>
</head><body onload='init();'>
  <h1>Serving Cramp::Websocket and normal Rack app on the same port</h1>
  <p id='log'></p>
</body></html>
EOF
    ]
  end
end

app = HttpRouter.new do
  add('/socket').to SocketApp
  add('/').to WebApp.new
end

run app

如果您想自己尝试这一点,请将此代码放入名为config.ru的文件中并运行thin start。您需要安装宝石thincramphttp_router

这样做的想法是,JavaScript代码与ws://localhost:3000/socket建立一个WebSocket连接,该连接与发送给它的消息相呼应,但这并不像预期的那样工作。open事件触发,在发送消息时没有错误,但我们永远得不到响应。

从服务器的角度来看,由于没有打印Client connected消息,因此没有建立连接。

使用thin start -D,我可以看到HTTP101正在发生,并且正在交换一些二进制数据。

我做错了什么?

Update:如果我将文件分成两部分,取出HttpRouter,并在不同的端口上运行两个thin实例,它仍然不能工作。因此,问题在于套接字代码,而不是HttpRouterWebApp

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-05-05 21:32:48

嗯,这是作弊,但我最终通过切换到另一个库:websocket机架解决了这个问题。对于好奇的人,更正后的代码如下:

代码语言:javascript
复制
require 'thin'
require 'http_router'
require 'rack/websocket'

class SocketApp < Rack::WebSocket::Application
  def on_open(env)
    puts 'Client connected'
  end
  def on_close(env)
    puts 'Client disconnected'
  end
  def on_message(env, message)
    puts "Got message: #{message}"
    send_data 'Here is your reply'
  end
end

class WebApp
  def call(env)
    [200, { 'Content-Type' => 'text/html' }, <<EOF
<html><head>
<script>
  function init() {
    function log(msg) { document.getElementById('log').innerHTML += msg + '<br>'; }
    var socketUri = 'ws://' + document.location.host + '/socket';
    log('Socket URI: ' + socketUri);
    var socket = new WebSocket(socketUri);
    socket.onopen = function(e) {
      log('onopen');
      socket.send('Is there anybody out there?');
      log('sent message');
    };
    socket.onclose = function(e) {
      log('onclose; code = ' + e.code + ', reason = ' + e.reason);
    };
    socket.onerror = function(e) {
      log('onerror');
    };
    socket.onmessage = function(e) {
      log('onmessage; data = ' + e.data);
    };
  }
</script>
</head><body onload='init();'>
  <h1>Serving WebSocket and normal Rack app on the same port</h1>
  <p id='log'></p>
</body></html>
EOF
    ]
  end
end

app = HttpRouter.new do
  add('/socket').to(SocketApp.new)
  add('/').to(WebApp.new)
end

run app
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10465659

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档