1

I'm interested in long-polling - can it be implemented via URLLoader in as3? I've got a php backend that periodically checks for updates, and should push them back to the client. I don't want to use sockets (had tons of issues with antiviruses and firewalls in recent project).

So basically:

  1. Client sends post\get request to php script via URLLoader.
  2. php checks for update, if there is any sends them back, if not, sleeps for 500 ms, than checks again.
  3. Client receives update - and repeats from step 1.

I'm guessing the main question is - will URLLoader\or URLRequest close this connection on timeout, and can I configure it somehow, to wait for update, lets say for 1 minute?

Drabuna
  • 1,225
  • 1
  • 14
  • 18
  • Great question. But I think it's been posed more directly - http://stackoverflow.com/questions/2690918/whats-the-timeout-on-urlloader-load-connection/2691495#2691495 – prototypical Oct 20 '13 at 17:48
  • Not exactly answers my questions. I understand that I can timeout it and close, but what if I want to keep connection opened for longer periods of time, without creating a new connection? – Drabuna Oct 20 '13 at 18:12
  • Read it, it does answer it. It's not something you can control via AS3. – prototypical Oct 20 '13 at 20:19
  • "The timeout comes from the system proxy settings", meaning if you want to modify it, you aren't getting it done via AS3. AS3 is just waiting for a response and the system determines what that response is and how long it's going to wait. – prototypical Oct 20 '13 at 20:20
  • Flex framework used to have an implementation of persistent connection over HTTP, but I cannot find the sources... HTTP 1.1 allowed one to build on top of it a protocol that used persistent connection (or simply didn't disconnect unless told to). It was called RFC-something-something-socket, but kill me if I remember the RFC number :/ Another idea: use this: https://github.com/gabriel/as3httpclient/tree/master it also explains how to set up policy server. –  Oct 20 '13 at 23:01
  • I think that if you will ask on the Apache Flex mailing list, they will tell you where to find the first socket thing I'm talking about. I think the author is still there. –  Oct 20 '13 at 23:02
  • 1
    He states in his question "I don't want to use sockets". Also, he's asking if he can configure the URLLoader or URLRequest. The answer is simply no. Undoubtedly there are socket based and other solutions, and likely questions with answers to that question on this site as well. – prototypical Oct 21 '13 at 00:29
  • Also, if you look in the secondary answer to the link I gave, you'll see this "If you are intending to hold a connection to the server and don't want it to close due to timeouts, I suggest you have a look at URLStream. Then you can simply send some keep-alive bogus from the server." - That seems to fit the requirements you requested. – prototypical Oct 21 '13 at 00:35
  • @prototypical What I was talking about is not really a socket, it's a persistent connection that is created on top of HTTP protocol in one case and in another case - it is an implementation of HTTP protocol in AS3. In general, you cannot avoid using sockets when using HTTP because the later is entailed by the former (HTTP is not possible w/o sockets), however, what may vary is the degree of programmer's direct involvement with them. –  Oct 22 '13 at 08:21
  • The problem with `URLStream` is that it, like the rest of the built-in family disallows (or you may view it as incorrectly implements) some of the HTTP headers, some of them may be vital, or very instrumental for creating the connection of the type OP wants. –  Oct 22 '13 at 08:22
  • @wvxvw Like I said, there are other solutions socket based and otherwise. The point I was making is his question was in regards to URLLoader or a another AS3 solution being preferable. The solution in the link I suggested required no external library. And I think the accepted answer kind of suggests that my link and suggestions were what he was searching for. Not trying to argue pros/cons or implementation of URLStream, just helping to the right solution. – prototypical Oct 22 '13 at 20:22
  • @prototypical well, I think that "right" solution in this context is a moot point. The library exists for a reason (better implementation of HTTP), so I don't see why using it would be a problem. Certainly not something to be ashamed of... As per my experience: 1) the accepted answer isn't always the best one. 2) what suites the OP doesn't necessary suite everyone else who reads this question. So I don't see a problem with that. –  Oct 22 '13 at 20:31
  • Agreed, not saying that this solution was binary. Sorry, was not insinuating that it was the holy grail or something. By right, I meant I was trying to get him to the right solution for him, and the details of URLStream seemed to fit his requirements well and the simplest (imo). – prototypical Oct 22 '13 at 20:41

1 Answers1

2

Thanks for all of your comments. I've made a test app to check if URLStream can do what I want, and it does. So, PHP code:

<?php
header('Content-Type: application/json; charset=utf-8');

$sleepTime=1*1000000; //every second

$endTime=time()+60*1; //after one minute

while(time()<$endTime)
{
    usleep($sleepTime);
    pushRandom();
}
echo json_encode(array('time'=>time(), 'message'=>'Bye world!'));
flush();
ob_flush();

function pushRandom()
{
    echo json_encode(array('time'=>time(), 'number'=>  rand(1, 10000)));
    flush();
    ob_flush();
}
?>

What it does - echoes a JSON object every second for a minute. After that echoes Bye World, and finished the polling.

And as3 code:

package com.drabuna.as3longpoll
{
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.net.URLRequest;
    import flash.net.URLStream;
    import flash.utils.ByteArray;

    public class LongPoll extends EventDispatcher
    {
        private var url:String;
        private var urlRequest:URLRequest;
        private var urlStream:URLStream;

        private var bytesRead:int=0;

        public function LongPoll(serverURL:String)
        {
            url=serverURL;
        }

        public function startPolling():void
        {
            urlRequest=new URLRequest(url);
            urlStream=new URLStream();
            urlStream.addEventListener(ProgressEvent.PROGRESS, onPollData);
            urlStream.addEventListener(Event.COMPLETE, onPollFinished);
            urlStream.addEventListener(IOErrorEvent.IO_ERROR, onPollError);
            urlStream.load(urlRequest);
        }

        public function endPolling():void
        {
            if(urlStream.connected)
            {
                urlStream.close();
            }
        }

        private function onPollData(e:ProgressEvent):void
        {
            if(urlStream.bytesAvailable>bytesRead)
            {
                var byteArray:ByteArray=new ByteArray();
                urlStream.readBytes(byteArray, bytesRead, urlStream.bytesAvailable-bytesRead);

                var tempString:String=byteArray.readUTFBytes(byteArray.bytesAvailable);

                var error:Boolean=false;
                try
                {
                    var jsonObject:Object=JSON.parse(tempString);

                }
                catch(e:Error)
                {
                    error=true;
                }

                if(!error)
                {
                    bytesRead=urlStream.bytesAvailable;
                    var evt:LongPollEvent=new LongPollEvent(LongPollEvent.POLL_DATA);
                    evt.data=jsonObject;
                    this.dispatchEvent(evt);    
                }
            }
        }

        private function onPollFinished(e:Event):void
        {
            var evt:LongPollEvent=new LongPollEvent(LongPollEvent.POLL_FINISHED);
            this.dispatchEvent(evt);
        }

        private function onPollError(e:IOErrorEvent):void
        {
            var evt:LongPollEvent=new LongPollEvent(LongPollEvent.POLL_ERROR);
            evt.data=e;
            this.dispatchEvent(evt);
        }

    }
}

A simple class that reads the stream, and parses it into as3 objects. Everything works fine!)

Drabuna
  • 1,225
  • 1
  • 14
  • 18