Ruby和WebSockets:浏览器的TCP

HTML5中的WebSockets从一开始就被设计成数据无关的(二进制或文本),并支持全双工通信。WebSockets是用于web浏览器的TCP。与BOSH或其他类似工具不同,它们只需要一个连接,这意味着服务器和客户机都能更好地利用资源。同样,WebSockets支持代理和防火墙,可以在SSL上操作,并利用HTTP通道来完成上述所有功能——您现有的负载均衡器、代理和路由器都可以正常工作。

浏览器中的WebSockets: Chrome、Firefox和Safari

jQuery帮助下的一个最小示例:

<html>

  <head>

    <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js'></script>

    <script>

      $(document).ready(function(){

        function debug(str){ $("#debug").append("<p>"+str+"</p>"); };

        ws = new WebSocket("ws://yourservice.com/websocket");

        ws.onmessage = function(evt) { $("#msg").append("<p>"+evt.data+"</p>"); };

        ws.onclose = function() { debug("socket closed"); };

        ws.onopen = function() {

          debug("connected...");

          ws.send("hello server");

        };

      });

    </script>

  </head>

  <body>

    <div id="debug"></div>

    <div id="msg"></div>

  </body>

</html>

上面的例子展示了WebSockets的双向特性:send向服务器推送数据,onmessage callback在服务器向客户端推送数据时被调用。不需要长轮询、HTTP头开销或杂耍多个连接。

流数据到WebSocket客户端

WebSockets与原始TCP套接字不同,这是有原因的。虽然从浏览器内部打开原始TCP连接看起来很诱人,但浏览器的安全性将立即受到威胁:任何网站都可以在与用户相同的安全上下文中代表用户访问网络。例如,一个网站可以打开一个远程SMTP服务器的连接并开始发送垃圾邮件——一个可怕的想法。相反,WebSockets通过定义一个特殊的握手来扩展HTTP协议,以便浏览器建立连接。换句话说,它是一种选择加入协议,需要一个独立的服务器。

没有什么可以阻止您通过原始协议与SMTP、AMQP或任何其他服务器进行通信,但是您必须引入WebSocket服务器作为连接的中介。Ruby EventMachine也允许我们用几行代码构建一个非常简单的事件驱动的WebSocket服务器:

require 'em-websocket'
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |ws|
     ws.onopen { ws.send "Hello Client!"}
     ws.onmessage { |msg| ws.send "Pong: #{msg}" }
     ws.onclose { puts "WebSocket closed" }
end

消费型WebSocket服务

一个常规的Ruby HTTP客户端也应该能够处理WebSockets:

require 'eventmachine'
require 'em-http-request'
EventMachine.run {
     http = EventMachine::HttpRequest.new("ws://yourservice.com/websocket").get :timeout => 0
     http.errback { puts "oops" }
     http.callback {
         puts "WebSocket connected!"
         http.send("Hello client")
     }
     http.stream { |msg|
         puts "Recieved: #{msg}"
         http.send "Pong: #{msg}"
     }
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容