Multiuser Chat using Flex and Ruby

For the last few days I had been googling for some good help for coding networked flash applications for a pet project of mine. Mostly using Flex & Ruby. There have been quite a few I saw – made with flash and using Java; but nothing to my personal liking. And hence I set to build a prototype of my own.

Being a coder and a poor (financially & aesthetically & skillfully :D) visual designer, I am totally in love with Flex for the visual quality it brings to the flash applications i can build.

Ruby for the beauty it brings to the code; but then the code is only as good as the coder. And for cooking up a quick prototype, no language has been so good of course except for Perl (for me ofcourse).

Multiplayer – thats a tricky question. Flash cannot support P2P (peer-to-peer) applications as yet. So the best choice available is to use a client-server architecture – the good ole’ sockets.

Hence using the code from a lot of different places and porting them from other languages, I managed to quickly cook up a Flex multiuser chat application with a ruby backend. Without further ado, into the code.

The server right now runs on the 9999 port of the localhost and the client connects to the same host and port. If you plan to test it on a hosting server, make sure you change the host and the port.

Note: My wordpress code plugin is fucking up the mxml code. For this part you may just download the zip file and use the client.mxml.

The Flex client:

< ?xml version="1.0"?>

		< ![CDATA[
			import flash.display.Sprite;
			import mx.controls.Alert;
			public var socket:XMLSocket = new XMLSocket();
			private var host:String     = "localhost";
			private var port:int        = 9999;
			public function init():void	{
				socket.connect(host, port);
				socket.addEventListener(DataEvent.DATA, onData);
				socket.addEventListener(Event.CONNECT, onConnect);
				socket.addEventListener(Event.CLOSE, onClose);
				socket.addEventListener(IOErrorEvent.IO_ERROR, onEvent);
			private function onConnect(event:Event):void	{
				board.htmlText += "Client: Connected to server" + "
"; } private function ReconnectHandler(event:CloseEvent):void { if (event.detail == Alert.YES) init(); } private function onClose(event:Event):void { board.htmlText += "Disconnected from server" + "
";"Reconnect to the chat?", "Reconnect?", (Alert.YES | Alert.NO), this, ReconnectHandler); } private function onEvent(event:Event):void { board.htmlText += "Error" + "
"; trace(event); } private function onData(event:DataEvent):void { board.htmlText += event.text; } private function sendMesg():void { socket.send(username.text+ ': ' + mesg.text + "n"); mesg.text = ""; } ]]>
.marginstyle { paddingTop:12; paddingBottom:12; paddingLeft: 12; paddingRight: 12; } .spacestyle { paddingTop:2; paddingBottom:2; paddingLeft: 2; paddingRight: 2; }

To compile it to a swf
Assuming you already have the free Flex SDK just use
$> mxmlc client.mxml
which will create a client.swf file for you.

Multiuser Ruby chat server:

require 'socket'

MSGS = {"init"    => "Server started. Waiting for connections...",
        "welcome" => "Welcome! type EXIT to quit",
        "byebye"  => "Disconnected from server"}

EOF     = "00"
HOST		= "localhost"
PORT		= 9999

server	=, PORT)
puts MSGS["init"] 

# array to store all the active connections
sessions = []
while (session = server.accept)
  # push the current session(socket) in the array
  sessions < < session
  # initialize a new thead for each connection do |local_session|
		local_session.puts "#{MSGS["welcome"]}" + EOF

    # each time a client sends some data send it to all the connections
      data = local_session.gets
			if !data.nil?
				delim_pos = data.index(":")
				name      = data[0..delim_pos-1]
				data      = data[delim_pos+1..-1]

				if data[0] == EOF
					data = data[1..-1] 
				elsif data.chomp == "EXIT"
					local_session.puts "#{MSGS["byebye"]}" + EOF
					data = "#{name} disconnected from the server" + EOF

      sessions.each do |s| 
          s.puts "#{name}: #{data.chomp}" + EOF
        rescue Errno::ECONNRESET
          # an exception is raised, that means the connection to the client is broken

To Run
User ruby chat_server.rb

Source Code: Download here. It contains a simple single user server – java & ruby versions [ & server.rb], a multiuser server [chat_server.rb] and the client [client.mxml].

Anyone, any doubts can leave a comment.

8 Thoughts to “Multiuser Chat using Flex and Ruby

  1. I’m not sure if you’re still checking these comments, but it doesn’t seem to work if I run it over a network (instead of as a local file). Did you test it? I had the same problem when I tried to create a socket server in ruby myself.

  2. @sean hess
    hi sean. hmmm uf you are running it over the network, you will have to see that the swf has access to sockets. if the server/client are behind a firewall, i doubt that the socket access wont be available.

    btw is the socket server on a shared hosting?

  3. flash will need to accept policy request file which should be handled by ruby server.. for example in php 🙂

    if(substr($buff,0, 22) == “”) // this message received from flash
    echo “[“.date(‘Y-m-d H:i:s’).”] – FLASH POLICY FILE REQUESTn”;

    /* after request, close the POLICY socket */
    $index = array_search($clientSocket, $arrSocket);
    socket_shutdown($clientSocket, 2);

  4. repost because some code missing when i submit.. dont know why

    if(substr($buff,0, 22) == “<policy-file-request/__>”)
    echo “[“.date(‘Y-m-d H:i:s’).”] – FLASH POLICY FILE REQUESTn”;
    $contents='<? xml version=”1.0″?>< cross-domain-policy >’;
    $contents.='<allow-access-from domain=”*” to-ports=”9999″ />’;
    $contents.='< /cross-domain-policy>’;

    /* after request, close the POLICY socket */
    $index = array_search($clientSocket, $arrSocket);
    socket_shutdown($clientSocket, 2);

  5. Hi, im using this example but with the java server class… well i dont know if it connect to but when i type something in the inputbox the server get null and it close.. any help?

Leave a Reply

Your email address will not be published. Required fields are marked *