注意: 这个系列文章非常好: https://www.rails365.net/articles/websocket-xu-lie-wen-zhang-mu-lu 可以作为 0 基础的同学的入门
websocket 是基于web的类似于socket协议的一种东东。 不过 websocket 与 socket的关系,就好像javascript 与 java的关系, 巴基斯坦与卡巴斯基的关系,张三与张三丰的关系。。。 Orz 有基巴关系。。。
windows 下的失败原因: windows下出现各种诡异问题,无法解决。 例如: 无法运行.bat, .cmd脚本,无法直接运行ruby命令。 github issues页面也没有给出解释。
http的特点:
1. 单方面请求。 (浏览器 -> 服务器)
2. 无法保存状态
socket特点:
1. 双方向请求。
2. 有状态。
websocket 也分成 80端口(ws://) 和 433端口(wss://)
可以使用这个server 来实现任何后端语言: https://github.com/joewalnes/websocketd
1. 先在本机安装个 websocket server: 见上图github. 下来下来就是个二进制文件。
2. 使用一个 sh 脚本。 如下:
$ chmod +x test_echo.sh $ ./test_echo.sh 1 2 3 4 5 6 7 8 9 10
3. 使用 websocketd 来运行( 务必记得 对应的脚本是有权限的)
websocketd --port=3333 ./test_echo.sh
4. 打开一个html文件,内容如下:
<html> <pre id="log"></pre> <script> function log(msg){ document.getElementById('log').textContent += msg + '\n'; } var ws = new WebSocket('ws://localhost:3333'); ws.onopen = function(){ log('connect') } ws.onclose = function(){ log('close') } ws.onmessage = function(event){ log('message: ' + event.data) } </script> </html>
可以看出, 客户端的几个关键方法:
onopen, 打开时调用
onclose, 关闭时调用
onmessage, 收到消息时调用
Rails 4.2 中使用websocket
需要跟 tubesock, redis , rails 一起使用。参考: https://www.rails365.net/articles/websocket-zhi-yong-tubesock-zai-rails-shi-xian-liao-tian-shi-wu
1. 新建一个action: /welcome/chat , 这个action 就是专门复杂处理socket 请求的。可以认为这个action就承担着 websocket服务器的职能。 它的访问链接是: ws://localhost:3000/welcome/chat
代码如下:
#Gemfile: (版本号随意)
gem 'tubesock'
gem 'puma', '3.11.0'
gem 'redis-rails', '5.0.2'
# routes.rb get '/welcome/chat' => 'welcome#chat' get '/welcome/test_chat' => 'welcome#test_chat' # welcome_controller.rb: include Tubesock::Hijack def chat hijack do |tubesock| redis_thread = Thread.new do Redis.new.subscribe "chat" do |on| on.message do |channel, message| tubesock.send_data message end end end tubesock.onmessage do |m| Redis.new.publish "chat", m end tubesock.onclose do redis_thread.kill end end end # config/application.rb 中,增加: config.cache_store = :redis_store, "redis://localhost:6379/2/cache", { expires_in: 90.minutes } 否则会报错。 报莫名其妙的错误。 (不看full stack trace 看不出来。 看了之后也只能大体猜到是redis的问题, 没配置好。)
2. 记得,在上一步的时候, redis 要启动 (telnet localhost 6379)
3. 然后,我们就可以在 web browser的console中,测试一下:
socket = new WebSocket("ws://localhost:3000/welcome/chat") WebSocket {url: "ws://localhost:3000/welcome/chat", readyState: 0, bufferedAmount: 0, onopen: null, onerror: null, …}
4. 我们接下来,就可以单独写一个页面了。 (注意要新增一个erb页面: test_chat )
<h1>Tubesock Chat</h1> <pre id="output"></pre> <form class="chat"> <input placeholder="hello world" autofocus> </form> <script src="http://cdn.bootcss.com/jquery/1.9.1/jquery.js"></script> <script> jQuery(function(){ socket = new WebSocket("ws://localhost:3000/welcome/chat") socket.onmessage = function(event) { if(event.data.length){ $("#output").append(event.data + "<br />") } } $("body").on("submit", "form.chat", function(event){ event.preventDefault() $input = $(this).find("input") socket.send($input.val()) $input.val(null) }) }) </script>
在Rails中增加websocket, 需要注意的是:
1. 一旦controller创建好之后(controller, Gemfile ) ,如果页面没有实际内容的操作代码, 页面会一直转圈,但是不会显示任何内容。等一会儿就会报错。
实际上,我们看下后台,会发现,后台的日志中, 有
17:00:50 INFO: Completed -1 in 64ms (Views: 1.0ms | ActiveRecord: 9.5ms)
这个就说明成了。