Search code examples
socketsactionscriptmxmlflash-builder

Connect ActionScript class (Socket) with mxml Script code


my problem is the following:

I have an actionscript class that represents a socketclient. This code works. In addition to that I have a Main.mxml file with fx:script code (In my original file there is a huge GUI connected, in this case here I made it simple)

So what I want: I want to call methods when receiving information from the Socket. So I would like to call methods that are in the mxml file from the actionscript class. As an alternative I want to send events to the mxml file that can be processed there. I read a lot about import/include stuff and so on, but nothing really helped.

So here is my code: Actionscript file SocketExample.as:

// http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/Socket.html

package {
import flash.display.Sprite;

public class SocketExample extends Sprite {
    private var socket:CustomSocket;

    public function SocketExample() {
        socket = new CustomSocket("localhost", 80);
    }
}
}

import flash.errors.*;
import flash.events.*;
import flash.net.Socket;

class CustomSocket extends Socket {
private var response:String;

public function CustomSocket(host:String = null, port:uint = 0) {
    super();
    configureListeners();
    if (host && port)  {
        super.connect(host, port);
    }
}

private function configureListeners():void {
    addEventListener(Event.CLOSE, closeHandler);
    addEventListener(Event.CONNECT, connectHandler);
    addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
    addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
    addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
}

private function writeln(str:String):void {
    str += "\n";
    try {
        writeUTFBytes(str);
    }
    catch(e:IOError) {
        trace(e);
    }
}

private function sendRequest():void {
    trace("sendRequest");
    response = "";
    writeln("GET /");
    flush();
}

private function readResponse():void {
    var str:String = readUTFBytes(bytesAvailable);
    response += str;
    trace(response);



    //
        //  Here I want to call the method 
    //
}

private function closeHandler(event:Event):void {
    trace("closeHandler: " + event);
    trace(response.toString());
}

private function connectHandler(event:Event):void {
    trace("connectHandler: " + event);
    sendRequest();
}

private function ioErrorHandler(event:IOErrorEvent):void {
    trace("ioErrorHandler: " + event);
}

private function securityErrorHandler(event:SecurityErrorEvent):void {
    trace("securityErrorHandler: " + event);
}

private function socketDataHandler(event:ProgressEvent):void {
    trace("socketDataHandler: " + event);
    readResponse();
}
}

Here is the Main.mxml file called HelloSocket.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                   xmlns:s="library://ns.adobe.com/flex/spark" 
                   xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>


<fx:Script>
    <![CDATA[
        public function HelloWorld():void{
            HelloLabel.text = "Hello World";
        }


    ]]>
</fx:Script>
<s:Label id="HelloLabel" x="150" y="180" text="Hello" fontSize="20" fontWeight="bold"/>
</s:WindowedApplication>

so HelloWorld() is the function I want to call here. Important is also that GUI and SocketClient (as class) are running at the same time. This is the complete example code that I have.

Please tell me everything I need to make this example work, beginning from imports and includes, to event handling or method calling

Best would be to change directly my code and explain. I thank you very much in advance

If you would like to test it, here is a matching java socket server:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;


public class SocketServer {
public static void main (String args[]) throws IOException {

      ServerSocket mySocketServer = new ServerSocket(80);

      System.out.print("Waiting for FlashClient ...\n");
      Socket mySocket = mySocketServer.accept();

      System.out.print("FlashClient connected.\n\n");

      mySocketServer.close();   

      InputStream in = mySocket.getInputStream();
      OutputStream out = mySocket.getOutputStream();

      byte buffer[] = new byte[1];
      int i = 5;

      do
      {
        // i = in.read(buffer, 0, 1);
        if (i>-1)  out.write("Hello World".getBytes("UTF-8"));
        try {
            Thread.sleep (300);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
      } while(i>-1);

      System.out.print("Lost connection to FlashClient.\n\n");

      in.close();
      out.close();

      mySocket.close();

}

}

Solution

  • Thank you Christophe. So here is the solution to my problem.

    First, I needed an instance of the actionScript in the script are of my mxml file:

    protected var socketEx:SocketExample = new SocketExample();
    

    Then I had to change the methods in my mxml file a bit:

            protected function HelloWorld(event:FlexEvent):void
            {
                socketEx.socket.addEventListener("test", Function1);
    
            }
    
            protected function Function1(e:Event):void{
                HelloLabel.text = "World";
            }
    

    The HelloWorld method is called on creationComplete It adds an EventListener. The event is dispatched in my actionScript class:

    private function readResponse():void {
        var str:String = readUTFBytes(bytesAvailable);
        response += str;
    
        trace(response);
    
        this.dispatchEvent(new Event("test"));
    
    }
    

    So to use it here is the complete code now: SocketExample.as : // http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/Socket.html

    package {
    import flash.display.Sprite;
    
    public class SocketExample extends Sprite {
        public var socket:CustomSocket;
    
        public function SocketExample() {
            socket = new CustomSocket("localhost", 80);
        }
    }
    }
    
    import flash.errors.*;
    import flash.events.*;
    import flash.net.Socket;
    
    class CustomSocket extends Socket {
    public var response:String;
    
    public function CustomSocket(host:String = null, port:uint = 0) {
        super();
        configureListeners();
        if (host && port)  {
            super.connect(host, port);
        }
    }
    
    private function configureListeners():void {
        addEventListener(Event.CLOSE, closeHandler);
        addEventListener(Event.CONNECT, connectHandler);
        addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
        addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
    }
    
    private function writeln(str:String):void {
        str += "\n";
        try {
            writeUTFBytes(str);
        }
        catch(e:IOError) {
            trace(e);
        }
    }
    
    private function sendRequest():void {
        trace("sendRequest");
        response = "";
        writeln("GET /");
        flush();
    }
    
    private function readResponse():void {
        var str:String = readUTFBytes(bytesAvailable);
        response += str;
    
        trace(response);
    
        this.dispatchEvent(new Event("test"));
    
    }
    
    private function closeHandler(event:Event):void {
        trace("closeHandler: " + event);
        trace(response.toString());
    }
    
    private function connectHandler(event:Event):void {
        trace("connectHandler: " + event);
        sendRequest();
    }
    
    private function ioErrorHandler(event:IOErrorEvent):void {
        trace("ioErrorHandler: " + event);
    }
    
    private function securityErrorHandler(event:SecurityErrorEvent):void {
        trace("securityErrorHandler: " + event);
    }
    
    private function socketDataHandler(event:ProgressEvent):void {
        trace("socketDataHandler: " + event);
        readResponse();
    }
    }
    

    HelloSocket.mxml:

    <?xml version="1.0" encoding="utf-8"?>
    <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                       xmlns:s="library://ns.adobe.com/flex/spark" 
                       xmlns:mx="library://ns.adobe.com/flex/mx"
                       creationComplete="HelloWorld(event)">
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
    
    
    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;
            protected var socketEx:SocketExample = new SocketExample();
    
            protected function HelloWorld(event:FlexEvent):void
            {
                socketEx.socket.addEventListener("test", Function1);
    
            }
    
            protected function Function1(e:Event):void{
                HelloLabel.text = "World";
            }
    
    
    
        ]]>
    </fx:Script>
    <s:Label id="HelloLabel" x="150" y="180" text="Hello" fontSize="20" fontWeight="bold"/>
    </s:WindowedApplication>
    

    I hope that helps somebody. So this is how to send messages from a Java SocketServer (see code in my question) , receive it in flash and use it in the script code of the .mxml file