8.17 Socket File Loader
| The source of this example is found under the Examples/AS2/26_pro_socketFileLoader folder. |
With the introduction of ByteArrays in ActionScript 3.0/Flash Player 9 we can finally stream binary data via http and socket.
The new feature allows developers to transfer objects and assets (images / swf files)
through the network, enabling several interesting "tricks" that we can use to secure our SmartFoxServer based applications.
One of the most interesting uses of this new Flash Player feature is to bypass the browser's cache in order to "hide" important pieces of the application and strengthen the overall level of security. One of the captivating feature of ByteArrays is that you can easily manipulate them via ActionScript at runtime, opening the doors to advanced techniques like using runtime data compression, garbling, encryption etc...
The application presented in this tutorial will guide you through the simple steps that are necessary to read files from the server side and stream them to the client via socket.
» Binary data and Flash sockets
Before we proceed with the description of this example it is important to see what happens at the lowest level of communication
between Flash and SmartFoxServer.
All versions of Flash Player < 9 connect via socket using the XMLSocket class which uses a fixed protocol based on 0-byte terminated strings.
In other words the XMLSocket doesn't support a real binary protocol but it is limited to sending strings terminated by a 0x00 byte.
In order to maintain compatibility with older versions of the Flash Player, SmartFoxServer doesn't support a full binary protocol, yet. In fact, as of today (December 2007), the number of applications and games done in ActionScript 3 are still a small percentage compared to those created in AS 2.0. In future releases SmartFoxServer PRO will definitely support the new binary sockets provided by the Flash Player 9.
NOTE:
Even if maintaining XMLSocket compatibility may sound limiting for ActionScript 3 applications, you will be surprised to learn that the byte-terminated protocol is actually very efficient when sending small packets at a very high rate (i.e. in realtime games).
This is because it is required one single byte to determine the end of a message, while in binary form each message comes with a fixed-length header which usually takes at least 8 bytes, providing a larger overhead.
In order to be able to stream binary data using the XMLSocket class we use a Base64 representation of the data. Base64 is a very popular data format that allows binary data to be converted in plain text: one of the most popular application of this format is encoding file attachments in email messages. ( The ActionScript 3.0 Base64 class is provided by SubHero )
Learn more about Base64:
» The client side
The Flash CS3 example application is developed on a single frame and you can find the ActionScript code at the top of the timeline.
On the stage you find an empty movieclip used as a placeholder for loading the external assets and a combo box component which will contain three items to load.
The debug text area at the bottom of the stage will output the events received from the server.
The flow of the example application is very simple:
When the Load Image button is clicked the client sends a request to extension passing the id of the image to load:
function bt_load_click(evt:Event):void
{
// Prepare the array of parameters
var req:Array = []
// Store the id of the image that we want to load
req[0] = cb_images.selectedItem.data
// Send the request to the server, in String format
sfs.sendXtMessage("loader", "loadImg", req, SmartFoxClient.XTMSG_TYPE_STR)
}
The server will send the Base64 encoded file data, which is handled in a few lines of code:
function decodeImage( data:String ):void
{
var dec:ByteArray = Base64.decode64(data)
imgLoader.loadBytes(dec)
debugTrace("Image Loading Complete! TOT: " + dec.length + " bytes.")
}
Very simple, indeed!
» The server side
The server side extension is written in Java and it comes together with an open source Base64 implementation by Robert Harder. (NOTE: this class can be also used from any ActionScript and Python server extensions)
In this example a convention has been established so that the requested image name is made up of three parts: the first bit is img_, the second one is the image id (0,1,2) coming from the client side request and the third is the .jpg extension.
The server response is sent in String format where the first parameter is a 1 if the file was loaded successfully or a 0 if an error occurred. The second parameter in the response object is the actual Base64 encoded data of the image.
The encoding is performed in a very simple way, with the following code:
private String encodeFile(String filePath) throws IOException
{
String encodedData;
File input = new File(filePath);
// Prepare byte array according to the file size
byte[] byteData = new byte[(int) input.length()];
// Read data from file into byte array
FileInputStream inStream = new FileInputStream(input);
inStream.read(byteData);
// Encode in Base64
encodedData = Base64.encodeBytes(byteData, Base64.DONT_BREAK_LINES);
return encodedData;
}