Rails WebSocket介绍

那道卡了一个学期的生产者消费者问题,今夏开工,和小新讨论了半天怎么怎么折腾,然后踩到了不少坑。

需要用到Java+Rails+JavaScript,题目要求,不得不用。Java用于生产者消费者模型,剩下的用于前端显示。

最初的设计是轮询,换句话说,类似于Java写入数据库,然后刷新定时刷新读写,一遍遍去查找更新,这样当然是可行的,但是——好Low。

现在我们有了一个更好的解决方案,用WebSocket实现动态的、即时的更新。当然当初知识一个小想法,WebSockeet对我还很抽象,所以咨询了一下用过的小伙伴小新,得知差不多一个意思,查了各种资料,开工。

WebSocket的原理性介绍:https://github.com/abbshr/abbshr.github.io/issues/22

简单的来说是在运输层用TCP来进行通讯,而不是用HTTP协议,这很好理解嘛,跟Socket差不多一个意思(本来以为这辈子都不会用Socket因为不搞桌面开发)。

所以依旧的被切成三段,前端<->Rails,Rails<->Java,因为目前Java部分我还不是很懂,虽然复制黏贴了HTTP请求的代码,但具体怎么写的看不懂,就不做说明了。

参考一下一篇教程:WebSocket on Rails 4 and Ruby 2

可以结合Wiki来看,因为光看他的有点不明不白,光看Wiki也不太明白。(Example需要Bootstrap2,需要自行引入)。

摸索了两天,总算觉得自己懂了点什么,记录一下。

安装

不用说,先在GemFile里加上gem websocket-rails,然后bundle一下。

接下来运行rails g websocket_rails:install,进行WebSocket的安装。

接着在config/environments/development.rb里加入config.middleware.delete Rack::Lock移除这个中间件。

所有的准备步骤就做完了。

Controller

class ChatController < WebsocketRails::BaseController
  def initialize_session
    # perform application setup here
    controller_store[:message_count] = 0
  end
end

看这个实例,非常简单的一个Example,需要注意的是它的父类是:WebsocketRails::BaseController,而一般是ApplicationController,这两个是不一样的,用做WebSocket的Controller是没法作为普通Controller进行访问的。

controller_store之后进行解释。

那我们也别多说了,根据他的实例接着创建:

def new_message
    _message = {:message => 'this is a message'}
    send_message :new_message, _message
end

这里可能还无法理解,send_message是一个内置的函数,它与broadcast_message相对应,是用于给自己发送对象的,而broadcast_message是广播,给所有连接者。

接下来我们顺势讲Event Router,你就能懂发生了什么了。

Event Router

在config里找到event.rb,加入

subscribe :new_message, :to => ChatController, :with_method => :new_message

跟路由的语法很像,后面是Contrller以其对应的方法,那么前面自然是接下来我们要与前端向连的部分,叫做:new_message,而刚刚在Controller里,也就是这么一个东西。

JavaScript

很快的我们可以来到前端了,很简单的Demo即将结束。

我们先链接服务器:var dispatcher = new WebSocketRails('localhost:3000/websocket');,注意,在application.js中,websocket对应的JS一定要先引入,否则会没有该类。

是否连通,我们可以测试一下:

dispatcher.on_open = function(data) {
  console.log('Connection has been established: ', data);
  // You can trigger new server events inside this callback if you wish.
}

这段代码在连接上之后立即执行,data由WebSocket提供,不用管。

测试通过之后我们可以接着来了。

dispatcher.bind('new_message', function(data) {
    console.log('Daso:', data.message);
});

new_message,也就是刚才:new_message的部分,绑定一个事件,传入的是Object。

但是绑定不够,我们需要用trigger触发:

$('#hello').click(function(){
    dispatcher.trigger('new_message');
});    

很简单的触发过程。

普通的Controller

普通的Controller建立,使用按钮,你就能感受到了。

从前端发送消息

力的作用是相互的,Event Router也是一个桥梁,前端调用trigger('event_name', {})就能把数据传到后端,使用message[:xxx]来访问。当然没有实验过/w是看源代码感受到的。

从一般的Controller中数据

如果我们需要从HTTP协议获取数据,那么肯定会用到普通的Controller。

这里我们需要用到一个名叫Channels的东西,不复杂,甚至不需要你在Event Router里多写东西。

普通的Controller里加上一句

WebsocketRails[:channel_name].trigger(:event_name, object_to_send)

接下来在js里新建Channels

var channel = dispatcher.subscribe('channel_name');

// You can also pass an object to the subscription event
// var channel = dispatcher.subscribe({channel: 'channel_name', foo: 'bar'});

// bind to a channel event
channel.bind('event_name', function(data) {
  console.log('channel event received: ' + data);
});

触发同dispatcher,但需要注意的是,Channel的event只能由Channel触发,同理。

Data Store

Data Store有两种,上面我们或许已经见识过了——controller_storeconnection_store

connection_store类似于Session,是一个连接公用的数据。而controller_store针对个体的不同Controller数据就不能互通了,这是他们俩最大的区别,一般我们用Session比较多,同理。

结束

剩下的,Wiki依旧不能丢,这么说起来WebSocket也不难的样子~

植入部分

如果您觉得文章不错,可以通过赞助支持我。

如果您不希望打赏,也可以通过关闭广告屏蔽插件的形式帮助网站运作。

标签: 知识, 代码段, 语法, jQuery, Rails, WebSocket

已有 2 条评论

  1. 小刘

    大神,我在集成这个,socket连接的时候总是报500错误

  2. 小刀

    大神我的rails是5.1.4,按照你的步骤来的,但是就是连接不上
    this._conn = new WebSocket(this.url);这个地方报错 ,500
    我是哪里没有注意到吗,请帮帮忙,谢谢

添加新评论