Работаем с XMLSocket

А теперь самое интересное - делаем простой сервер на Ruby и флэш-клиент, который будет обмениваться данными с этим сервером с помощью XMLSocket.

Сервера на Ruby нам не нужно бояться. Он очень простой, укладывается в 18 строк кода. Сам я весьма поверхносно знаю Ruby, а это сделано на основе готового решения, нарытого в инете:

#!/usr/bin/ruby -w

puts 'Debug Server v 0.01'

policyInfo = '<?xml version="1.0"?>'
policyInfo += '<cross-domain-policy>'
policyInfo += '<allow-access-from domain="*" to-ports="4444,80" />'
policyInfo += "</cross-domain-policy>\0"

require 'socket'
server = TCPServer.new('localhost', 4444);

while(session = server.accept)

        Thread.new(session) do |s|

                s.print policyInfo

                while(msg = s.gets)
                        msg.strip!
                        puts msg
                        s.print msg
                end

        end

end

Сервер в бесконечном цикле ждет соединений от клиента. Для каждого соединения создает отдельный поток и сразу посылает клиенту policy-инфу, без которой флэш-плеер откажется работать с этим сокетом (подробности тут). Далее в следующем бесконечном цикле принимаются сообщения от клиента. Они выводятся в консоль и отправляются обратно клиенту. Вот и все.

Теперь клиентская часть:

/**
 * @author Yzh
 */

package;

import flash.system.Security;
import flash.net.XMLSocket;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.events.DataEvent;

class TrySocket
{
        // properties
        private var socket:             XMLSocket;

        // constructor
        public function new()
        {
                try
                {
                        Security.loadPolicyFile('xmlsocket://localhost:4444');

                        trace('create socket');
                        this.socket = new XMLSocket('localhost', 4444);
                        this.socket.addEventListener(Event.CONNECT, OnConnect);
                        this.socket.addEventListener(DataEvent.DATA, OnData);
                        this.socket.addEventListener(Event.CLOSE, OnClose);
                        this.socket.addEventListener(IOErrorEvent.IO_ERROR, OnIOError);
                        this.socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, OnSecurityError);
                }
                catch(e:Dynamic)
                {
                        trace('sluchilos strashnoe!');
                        trace(e.toString());
                }
        }

        static public function main():Void
        {
                new TrySocket();
        }

        private function OnConnect(event:Event):Void
        {
                trace('Connected!');
                trace('send some data');
                this.socket.send('Hello\n');
                this.socket.send('How do you do?\n');
                this.socket.send('It`s work!!!\n');
        }

        private function OnData(event:DataEvent):Void
        {
                trace('OnData: ' + event.data);
        }

        private function OnClose(event:Event):Void
        {
            trace('connection closed');
        }

        private function OnIOError(event:IOErrorEvent):Void
        {
                trace('OnIOError');
                trace(event.toString());
        }

        private function OnSecurityError(event:SecurityErrorEvent):Void
        {
                trace('OnSecurityError');
                trace(event.toString());
        }

        public function toString():String { return 'TrySocket'; }              
}

Первым делом мы загружаем policy-данные
Security.loadPolicyFile('xmlsocket://localhost:4444');

Ruby-сервер сообщает флэш-клиенту, что он разрешает соединения с любого домена на порты 4444 и 80. Если флэш-клиент не получит эти данные, возникнет событие SecurityErrorEvent. Далее мы создаем XMLSocket, ждем установления соединения (событие Event.CONNECT), и пишем в сокет некоторые строки. Они отображаются в консоли сервера и возвращаются обратно клиенту, в метод OnData. Если закрыть клиента, на сервере ничего особенного не произойдет -- он будет ждать других подключений. Если остановить сервер, в клиенте сработает событие Event.CLOSE.

Хочу обратить внимание на один нюанс -- сервер должен заканчивать строку нулевым символом (zero byte), а клиент -- символом перевода строки.

В данном примере используется класс flash.net.XMLSocket, который работает со строковыми данными. Можно также использовать класс flash.net.Socket для работы с бинарными данными.

Дальше я собираюсь сделать дебаг-сервер на Ruby, который будет принимать отладочные сообщения от флэш-приложения и выводить их в консоль. А также, при необходимости, записывать их в лог-файл. Тогда отладка будет выглядеть следующим образом -- слева открыто окно с консолью дебаг-сервера, справа окно браузера и в нем флэш-приложение. Все, что во флэш-приложении передается функции trace, будет отображаться в консоли сервера.

Про отладку и возможности функции trace в haXe смотрите тут.