6

I managed to create a C# Server that sends files to AS3(AIR) Clients using sockets. On the AS3 side I'm using the flash.net.Socket library to receive the data through TCP.

This is how it works:
-> I turn on my server, and it listens for clients (plus I can create a list of connected devices);
-> I turn on my client and it automatically receives the data;

The trigger event to receive the data is made on the client, i.e., I simply turn the server ON and when the client turns ON, it gets the data, triggering these events:

socket.addEventListener(Event.CONNECT, onConnect); -> to connect to the server  
socket.addEventListener(Event.SOCKET_DATA, onDataArrival); -> to receive the data  

Now I want to do something different. I don't want to trigger it on the client, I want the server to do that, i.e, I want to turn on my client and on the server put in what client will get the data.

So why am I trying to make the client a client/server? Well, because my server is one machine, and my clients are XXX mobile devices that connect the server, and this is my approach to accomplish this.

So, given what I just said, I managed to create my AS3 client/server app that works just like I want it, using the flash.net.ServerSocket library.

First I put the client listening:

serverSocket.bind(portNumber, "10.1.1.212");
serverSocket.addEventListener(ServerSocketConnectEvent.CONNECT, onConnectServer);
serverSocket.listen();

And then I receive the data using the flash.net.Socket Event.SOCKET_DATA

And that's pretty much it. Works just like I want it to.
However, the flash.net.ServerSocket is not compatible with mobile devices, yet...

So here's my problem: I need to send files from C# server (that needs to listen for clients so I can create a list of connected devices) to AS3(AIR) Clients, but I have to define which client is getting the data on the server, and the clients need to be prepared to receive that data anytime, therefore, listening, but there's a lot of them, that's why I consider them as clients.

And my question is: Is there a way to make a client listen for incoming connections and triggering an event when it happens, whithout using the Server Socket in AS3?

Also, if you have a different approach to accomplish my goal whithout using the C# server <-> AS3 client/server logic, please feel free to kick in your opinion.

Schrödinger's Box
  • 3,218
  • 1
  • 30
  • 51

1 Answers1

6

Yes. Your client should connect to the server via a flash.net.Socket (doc) or flash.net.XMLSocket (doc). In most cases, you only need one server to which many clients can connect. It's not entirely clear why you have servers at both ends?

Edit:

Below is a quick example of a client continuously listening for messages from the server using a Socket. This connects to the server and then waits (indefinitely) for data. When a chunk of data is received (in this case I'm expecting strings terminated by a new line character), the data is passed along with an event.

If you've tried this approach without success, you should look to see if there's any errors or if the connection is getting closed.

Document class:

package  {
    import flash.display.Sprite;

    public class Main extends Sprite {
        protected var socket:SocketTest;

        public function Main() {
            this.socket = new SocketTest();
            this.socket.addEventListener(SocketMessageEvent.MESSAGE_RECEIVED, onSocketMessage);
            this.socket.connect("127.0.0.1", 7001);
        }

        protected function onSocketMessage(e:SocketMessageEvent):void {
            var date:Date = new Date();
            trace(date.hoursUTC + ":" + date.minutesUTC + ":" + date.secondsUTC + " Incoming message: " + e.message);
        }
    }
}

SocketTest class:

package  {
    import flash.net.Socket;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.SecurityErrorEvent;
    import flash.events.ProgressEvent;
    import flash.errors.IOError;

    public class SocketTest extends Socket {
        protected var _message:String;

        public function SocketTest() {
            super();
            this._message = "";

            this.addEventListener(Event.CONNECT, socketConnected);
            this.addEventListener(Event.CLOSE, socketClosed);
            this.addEventListener(ProgressEvent.SOCKET_DATA, socketData);
            this.addEventListener(IOErrorEvent.IO_ERROR, socketError);
            this.addEventListener(SecurityErrorEvent.SECURITY_ERROR, socketError);
        }

        protected function socketData(event:ProgressEvent):void {
            var str:String = readUTFBytes(bytesAvailable);

            //For this example, look for \n as a message terminator
            var messageParts:Array = str.split("\n");

            //There could be multiple messages or a partial message, 
            //pass on complete messages and buffer any partial
            for (var i = 0; i < messageParts.length; i++) {
                this._message += messageParts[i];
                if (i < messageParts.length - 1) {
                    this.notifyMessage(this._message);
                    this._message = "";
                }
            }
        }

        protected function notifyMessage(value:String):void {
            this.dispatchEvent(new SocketMessageEvent(SocketMessageEvent.MESSAGE_RECEIVED, value));
        }

        protected function socketConnected(event:Event):void {
            trace("Socket connected");
        }

        protected function socketClosed(event:Event):void {
            trace("Connection was closed");
            //TODO: Reconnect if needed
        }

        protected function socketError(event:Event):void {
            trace("An error occurred:", event);
        }
    }
}

SocketMessageEvent class:

package  {
    import flash.events.Event;

    public class SocketMessageEvent extends Event {
        public static const MESSAGE_RECEIVED:String = "messageReceived";

        protected var _message:String;

        public function SocketMessageEvent(type:String, message:String = "", bubbles:Boolean = false, cancelable:Boolean = false) {
            super(type, bubbles, cancelable);
            this._message = message;
        }

        public function get message():String {
            return this._message;
        }
    }
}

As a test I set the server up to send a message every 5 seconds, this is the output in the console:

Socket connected
21:36:24 Incoming message: Message from server: 0
21:36:29 Incoming message: Message from server: 1
21:36:34 Incoming message: Message from server: 2
21:36:39 Incoming message: Message from server: 3
21:36:44 Incoming message: Message from server: 4
21:36:49 Incoming message: Message from server: 5
david.emilsson
  • 2,313
  • 1
  • 20
  • 24
  • I'm already using the `flash.net.Socket` and I can read the data fine. But the trigger to receive it is on the client, not on the server. I search `flash.net.XMLSocket`, but with no luck. I updated my main thread with more info. – Schrödinger's Box Dec 19 '12 at 17:08
  • I still don't see the need for a server on each client. Just like in your original approach, let each client establish a socket connection to the server - and then keep the connection open. Let the server keep track of the connected devices and it is then capable of sending whatever data is needed to any connected device at any time. – david.emilsson Dec 19 '12 at 19:39
  • I have tried to do that, it triggers the CONNECT event and stays there, but when I send the package from the server, the SOCKET_DATA event isn't triggered. Maybe I'm missing something... – Schrödinger's Box Dec 19 '12 at 19:57
  • Added an example showing the basics of setting up a socket connection which is waiting for the server to send data. – david.emilsson Dec 19 '12 at 21:44
  • The approach you mentioned was the one I tried to use, but I'm guessing maybe my problem is on the server and not on the client. Here you can download my C# server: [http://sdrv.ms/ZTu3eg](http://sdrv.ms/ZTu3eg) Also, could you please post your server code? – Schrödinger's Box Dec 20 '12 at 12:42
  • I couldn't say for sure if there's a problem with your server code since I'm a bit rusty on my C#. However, you can use the client to debug the connection. Are you listening to the events I'm using in the example code above? If so, are you getting any errors? Is the connection closed? A good guess is that you receive a security sandbox error. In that case you need to look over your [crossdomain policy files](http://stackoverflow.com/questions/9515821/security-sandbox-violation-cant-connect-to-server-via-socket). – david.emilsson Dec 20 '12 at 14:30
  • I managed to get it working and the problem was on the server, not on the client. Although I figured out the correct AS3 before I posted this thread, it was thanks to you, walkietokyo, that I re-looked at my code and figured out where the problem was. That being said you did answer the thread question with the correct answer so I'm marking it as the answer. Thank you very much for the help. – Schrödinger's Box Dec 20 '12 at 18:31