EventMachine + WebSockets, #rorosyd talk

January 11 2012, 3:02 PM  by David Parry

EventMachine + WebSockets

This is the notes from a talk I gave at #rorosyd on the 10th of January 2012.

The demo code is available at: [https://github.com/suranyami/socket_demo][]

So, what’s EventMachine?

EventMachine supports lots of protocols!

There is a great list of currently implemented protocols at https://github.com/eventmachine/eventmachine/wiki/Protocol-Implementations which includes:

How to learn about EventMachine?

PeepCode

EventMachine Introduction

Example of a Trivial Telnet Server

require 'eventmachine'
class Echo < EM::Connection
  def receive_data(data)
    send_data(data)
  end
end

EM.run do
  EM.start_server(“0.0.0.0”, 10000, Echo)
end

So, what’s a WebSocket?

Where would I use it?

Trivial WebSocket server

require 'eventmachine'
require 'em-websocket'

conf = {:host => “0.0.0.0”, :port => 8080}

EM.run {
  EventMachine::WebSocket.start(conf) do |ws|
    ws.onopen {ws.send "Hello Client"}
    ws.onclose { puts "Connection closed" }
    ws.onmessage {|msg| ws.send "Echo: #{msg}"}
end }

A Less Trivial example

So, I wanted something to demo that wasn’t trying to do to much but demonstrated the real-time nature of WebSockets, so I built this little socket_demo site:

Useless, but non-trivial!

CoffeeScript

Assign an id to socket/guest

EM-Websocket Server:

class Demo constructor: –>
    if WebSocket?
      window.socket = new WebSocket("ws://192.168.1.3:7070")
    else
      window.socket = new MozWebSocket("ws://192.168.1.3:7070")

Register ourselves

CoffeeScript:

window.socket.onopen = –>
  window.socket.send JSON.stringify({kind: “register”})

EM-Websocket Server:

socket.onmessage do |msg|
  puts "Server Received #{msg}"
  id = @sockets[socket][“id”]
  incoming = ActiveSupport::JSON.decode(msg)
  case incoming[“kind”]
    when "register"
      socket.send(register_message(id).to_json)
      broadcast(id)
    else
      ## Send “add” event to everyone

EM-Websocket Server:

def send_to_all(message) @sockets.each do |destination|`
    destination.send(message.to_json)
end

CoffeeScript:

```coffeescript
window.socket.onmessage = (mess) –>
  data = jQuery.parseJSON(mess.data)
  switch data[“kind”]
  when "add"
      window.add_player data["id"], data["color"]

Send click events

$(“#red”).click (e) => window.socket.send JSON.stringify {kind: “update”, color: “red”}

$(“#green”).click (e) => window.socket.send JSON.stringify {kind: “update”, color: “green”}

Server gets a message

socket.onmessage do |msg|
  id = @sockets[socket][“id”] incoming = ActiveSupport::JSON.decode(msg)
  case incoming[“kind”]
    when “register”
      socket.send(register_message(id).to_json)
      broadcast(id)
    else
      if incoming["color"]
        color = incoming["color"]
        message = {"kind" => "update", "id" => id, "color" => color}
        @sockets[socket]["color"] = color
        send_to_all(message)
    end
  end
end

Live Demo

Then I gave a live demo where I used my laptop as an unsecured base station, and people connected to it with their iPhones and started clicking on the red/green buttons:

wifi: suranyami (no password) url: test.local:4567

How to do testing with EventMachine?

em-spec https://github.com/joshbuddy/em-spec

This demo code viewable here: [https://github.com/suranyami/socket_demo][]

September 11th, 2013 2:19pm