Sock - Simple AIR Sockets Manual (version 1.0)

Thanks for purchasing Sock - Simple AIR Sockets, a Socket Communication SWC component for Desktop AIR Applications. This Manual aims to give insight into some of the base functionality and usage of Sock - Simple AIR Sockets, but also into the underlying processes (since socket communication is mostly invisible).

To use Sock it's advised that you have at-least a basic understanding of Actionscript 3, this is not a AS3 guide/tutorial, it mostly deals with integrating Sock into existing projects, there is also a drag-able component for Flash CS5+ and all the example/tutorial files are included in the download (located in the EXAMPLES folder).

Chapters:

  1. Introduction to Sock
  2. Requirements & Installation (Flash Builder / Flash CS5+)
  3. Simple Sock setup
  4. The Widget
  5. Saving to XML & Data Handling
  6. Advanced Communication
  7. Other Examples
  8. Mobile communication
  9. Log messages
  10. Extra information

This manual is also available online (HTML version) at: http://www.frankdouwes.com/sock/manual/
The Sock ASDocs are located in the DOCS folder or available online at: http://www.frankdouwes.com/sock/docs/

Introduction to Sock

Sock is an AIR Socket server/client hybrid class with an XML save function attached to it (in a nutshell). It's simple to setup but has plenty of optional settings to make very complex communicative structures between multiple (AIR) applications running on multiple, or on a single, computer.

Sock was developed after I spent months dealing with sockets and socket-data on a semi-daily basis, developing a suite of apps that had to share/sync user settings amongst each-other, but also outside the AIR runtime environment, setting up a socket connection isn't the hardest thing in the world, making them work reliable across multiple apps keeping all data synced correctly is! To avoid this problem in the future I decided to develop a component that would save me a lot of time in the future, the result is Sock - Simple AIR Sockets!

During development extra time was spent trying to keep the base setup simple while providing plenty of optional properties and functions to make it as versatile as possible.

Highlights:

Things to know before you start using Sock:

Top

Requirements & Installation

Sock - Simple AIR Sockets requires adobe AIR runtime 3.1 or higher and was developed using the Flex SDK v4.6. Sock is packaged in a SWC file that needs to added to your project:

Adobe Flash (CS5+)

  1. Start a new AIR Project or open an existing AIR project
  2. Open the Actionscript Settings panel: go to File/ActionScript Settings
  3. Select the 'Library' tab
  4. Choose 'browse to SWC file' (little red icon, top right)
  5. Navigate to and select the Sock SWC component
  6. Choose 'Open' the SWC file should now be added to the library list
  7. Close the Actionscript Settings panel (by clicking the OK button)

Adobe Flash Builder (4+)

  1. Start a new AIR (for Desktop or Mobile) or open an existing AIR project
  2. Open the project properties panel: Right-click on the project folder and select 'Properties' from the dropdown menu
  3. Choose 'Actionscript Build Path'
  4. Select the 'Library path' tab
  5. Choose 'add SWC...' (system button located on the right)
  6. Navigate to and select the Sock SWC component
  7. Choose 'Open' the SWC file should now be added to the library list
  8. Close the Project properties panel (by clicking the OK button)

Instantiate Sock

Now all thats left to do is import the classes into your main class, and instantiate Sock:

package {	

	// import sock classes
	import sock.Sock;
	import events.CommEvent;
	
	public class Main {
		
		// add the sock instance
		public var mySock:Sock = Sock.getInstance();
		
		public function Main() {
			
			// initialize sock (as a server)
			mySock.initialize('mySock', 'server', '10.0.1.1', 4444, 5555);
			
			// or initialize sock (as a client)
			// mySock.initialize('mySock', 'client', '10.0.1.1', 4444, 5555);
		}
	}
}
Top

Simple Sock Setup

The completed source of this tutorial (both server and client) is located in the EXAMPLES folder (the source projects were created in flash CS5).

So lets get started! Imagine this: a museum asked you to develop something for their new exhibition, they have a video that needs to be projected onto a wall they would like visitor to be able to control the video from 25 meters away using a touch-screen.

You've created a 'VideoPlayer' application (a video player without any visual controls but with start/stop/pause/resume functionality), and the 'ControlPanel' application that has a visual control panel (a bunch of shiny buttons) that do nothing yet. Time to use Sock! All you have to do is decide which application will be the client, and which will be the server.

with just two applications (one instance of VideoPlayer and one instance of ControlPanel) always running, the choice really doesn't matter. So lets look at two different scenarios:

  1. The same video is being projected multiple times throughout the exhibition, on multiple locations (using multiple computers), but there is only one control panel, in this case each VideoPlayer would become a client and ControlPanel the server.
  2. The video is only projected once, but there are multiple control panels throughout the exhibition so multiple visitors can control the video at the same time, in this scenario VideoPlayer would be the server, and each ControlPanel a client.

Lets focus on Scenario 1

ControlPanel (server) setup:
package {	
	
	import flash.display.Sprite;
	import flash.events.*;
	
	// import sock classes
	import sock.Sock;
	import events.CommEvent;
	
	public class ControlPanel extends Sprite
	{
		
		// add the sock instance
		public var server:Sock = Sock.getInstance();
		
		public function ControlPanel() {
			
			// a listener for setupComplete
			server.addEventListener(Sock.ON_SETUP_COMPLETE , onCommunicationSetup);
			
			// initialize sock (server)
			server.initialize('ControlPanel', 'server', '10.0.1.1', 4444, 5555);
		}
		
		// after the client has completed setup
		private function onCommunicationSetup(e:Event):void {
			
			// add listeners to our buttons (example)
			playBtn.addEventListener(MouseEvent.CLICK, onPlay);
			stopBtn.addEventListener(MouseEvent.CLICK, onStop);
			pauseBtn.addEventListener(MouseEvent.CLICK, onPause);
			resumeBtn.addEventListener(MouseEvent.CLICK, onResume);
		}
		
		private function onPlay(e:MouseEvent = null):void {
			server.send('videoPlay', true);		//play video
		}
		
		private function onStop(e:MouseEvent = null):void {
			server.send('videoPlay', false);	//stop video
		}
		
		private function onPause(e:MouseEvent = null):void {
			server.send('videoPause', true);	//pause video
		}
		
		private function onResume(e:MouseEvent = null):void {
			server.send('videoPause', false);	//resume video
		}
	}
}
VideoPlayer (client) setup:
package {
	
	import flash.display.Sprite;
	import flash.events.Event;

	// import sock classes
	import sock.Sock;
	import events.CommEvent;
	
	public class VideoPlayer extends Sprite {
		
		// add the sock instance
		public var client:Sock = Sock.getInstance();
		
		public function VideoPlayer():void {
						
			// a listener for setupComplete
			client.addEventListener(Sock.ON_SETUP_COMPLETE , onCommunicationSetup);
			
			// a listener for every received case we're checking for	
			client.addEventListener(CommEvent.ON_UPDATED_CASE, onCommunicationUpdated);
			
			// initialize sock (client)
			client.initialize('VideoPlayer', 'client', '10.0.1.1', 4444, 5555);
		}
		
		// after the server has completed setup
		private function onCommunicationSetup(e:Event):void {
						
			// add test case (test for 'videoPlay' from all clients, parse as Boolean)
			client.addTestCase('all', 'videoPlay', 'boolean');
			
			// add test case (test for 'videoPause' from all clients, parse as Boolean)
			client.addTestCase('all', 'videoPause', 'boolean');
		}
		
		// this is where we get updates of cases we're testing for
		private function onCommunicationUpdated(e:CommEvent):void {
									
			if (e.caseName == 'videoPlay' && e.caseValue == true) {
				// execute the play function for the video player
			} else if (e.caseName == 'videoPlay' && e.caseValue == false) {
				// execute the stop function for the video player
			} else if (e.caseName == 'videoPause' && e.caseValue == true) {
				// execute the pause function for the video player
			} else if (e.caseName == 'videoPause' && e.caseValue == false) {
				// execute the resume function for the video player
			}
		}
	}
}

So how does this actually work?

On running the ControlPanel application, Sock sets up the server at the specified IP Address and starts listening for incoming connections to the specified ports. When everything is setup and running the onCommunicatioSetup() function is triggered where we add listeners to our buttons, when the user presses a button data is sent through the correct socket to the client (and in this case the client responds by playing/stopping/pausing or resuming the video).

On running the VideoPlayer application the sock client is initialized and looks for the Sock server at the specified IP and establishes a socket connection to the specified ports. When everything is setup and running the onCommunicatioSetup() function is triggered where we add our test cases. Test cases are combinations of application-names/case-names and their value(s) to test all incoming data against. When test cases are received the results are being parsed to the onCommunicationUpdated() function from which we trigger our VideoPlayer functions. you can have as many of these clients running at the same time a you want*.

All that's left to do now is hide the widgets and distribute your applications, simply insert one of the following lines above communicator.initialize(); to hide the widget on startup:

Hide the widget:
server.widget.visible = false;	// make server widget invisible
client.widget.visible = false;	// make client widget invisible

Compile your applications, install them on the various computers (make sure the server IP matches and that all firewall/router settings are correct), and you're done! Time to watch those visitors press those shiny touch-screen buttons during the exhibition opening, Awesome! Job well done!

Pretty simple right?, but that is really just scratching the surface of what you could do with Sock. For more options see the ASDoc or continue reading the next chapter.

Top

The Widget

The widget is a floating window that gives the developer insight in all server/client activity and settings. The widget is mostly for development, and is meant to be hidden/disabled once everything is setup/working/tested, allowing the server/client to run in the background. The widget contains a log displaying all recent activity and it gives you a bunch of options to help you debug:

Input field

The Widget contains an input field that allows you to send out strings, for example 'pauseVideo: true' or 'playVideo: false', great for testing your TestCases and/or listeners.

Panels

Buttons

Optional Properties:

The widget has optional settings, that have to be set before running the initialize() function

// some optional widget properties
mySock.widget.visible = false;
mySock.widget.scrollbar = false;
mySock.widget.alwaysInFront = true;

// initialize sock
mySock.initialize('mySock', 'client', '10.0.1.1', 4444, 5555);

Widget Toggle

During development it might be useful to have a button on your stage that shows or hides the widget, this can be achieved using the toggleWidget(); function:

myButton.addEventListener(MouseEvent.CLICK, mySock.widget.toggleWidget);

A complete list of properties/functions (with descriptions) is available in the ASDoc (located in the DOCS folder).

Top

Saving to XML & Data Handling

Sock - Simple AIR Sockets has the ability to save variables and their value(s) to XML, this XML is loaded/parsed on startup.

Saving data

By default saving is done by each client individually, Sock offers the option to save data in various ways:

Lets have a look at some examples, saving a simple form (with the textfields nameField, ageField, emailField):

private function onSaveBtnClick(e:MouseEvent = null):void {
	
	// save and send (with instaSave turned on)
	mySock.send('name', nameField.text, true, true);
	
	// or just save (with instaSave turned on)
	mySock.saveSetting('name', nameField.text, true);
}

It's also possible to combine various variables/value(s) and save them once like so:

private function onSaveBtnClick(e:MouseEvent = null):void {
	
	// disable instaSave on all and update settings at the end
	mySock.send('name', nameField.text, true, false);
	mySock.send('age', ageField.text, true, false);
	mySock.send('email', emailField.text, true, false);
	mySock.updateSettings();
	
	// or just save
	mySock.saveSetting('name', nameField.text, false);
	mySock.saveSetting('age', ageField.text, false);
	mySock.saveSetting('email', emailField.text, false);
	mySock.updateSettings();
}

Or to save them as a single (nested) object like so:

private function onSaveBtnClick(e:MouseEvent = null):void {
	
	var formData:Object = new Object();
	formData["name"] = nameField.text;
	formData["age"] = ageField.text;
	formData["email"] = emailField.text;
	
	// save and send
	// NOTE: in order to send objects mySock.useObjects = true; must be set (before initialize(); gets called)
	mySock.send('formData', formData, true, true);
	
	// or just save
	mySock.saveSetting('formData', formData.text, true);
}

Retrieving saved data

Use use the fetchSetting(); function to get previously saved data, you can specify a return type for example.

private function onSaveBtnClick(e:MouseEvent = null):void {
	
	// fetch name as string
	var name:String = mySock.fetchSetting('name', 'string');
	
	// fetch age as int
	var age:int = mySock.fetchSetting('age', 'int');
	
	// in case of saved nested objects
	var formData:Object = mySock.fetchSetting('formData', 'object');
	var name:String = formData[name];
	var age:int = formData[age];
	var email:String = formData[email];
}

Optional settings

Optional settings have to be set before running the initialize() function.

mySock.serverAutoSavesIncoming = true; 	// makes the server save all incoming data
mySock.allowSave = false; 	// disables saving (and the loading/parsing of the XML on startup)

// initialize sock
mySock.initialize('mySock', 'client', '10.0.1.1', 4444, 5555);

// some aditional sock data functions
mySock.clearSetting('formData', true);		// clear the value(s) of a particular saved variable
mySock.clearAllSettings(true);			// clear the value(s) of a all saved variable

mySock.deleteSetting('formData', true);		// delete a particular saved variable
mySock.deleteAllSettings(true);			// delete all saved variables

A complete list of properties/functions (with descriptions) is available in the ASDoc (located in the DOCS folder).

Top

Advanced Communication

Client to Client Communication

Let's go back to our imaginary exhibition, you did such an amazing job that museum asks you to develop another installation: they wants users to work in pairs (each on their own computer/touchscreen) to solve a problem/puzzle, and the pair who solves the problem the fastest gets their result projected on a wall somewhere, lets say there are 2 pairs (so 4 clients) and 1 projection (the server).

In this setup communication has to happen between the paired clients (but not all clients) and between all clients and the server, so how do we achieve this? quite simple, we give each client a unique name, and our testCases include the particular client name we'd like to receive data from.

the initialize functions could look like this:
// pair1 client1
p1c1.initialize('p1c1', 'client', '10.0.1.1', 4444, 5555);

// pair1 client2
p1c2.initialize('p1c2', 'client', '10.0.1.1', 4444, 5555);

// pair2 client1
p2c1.initialize('p2c1', 'client', '10.0.1.1', 4444, 5555);

// pair2 client2
p2c2.initialize('p2c2', 'client', '10.0.1.1', 4444, 5555);
some testCases could look like this:
// pair1 client1 adds a testCase for 'caseName' from from pair1 client2 (as a String)
p1c1.addTestCase('p1c2', 'caseName', 'string');

// pair2 client2 adds a testCase 'anotherCase' from pair2 client1 (as a int)
p2c2.addTestCase('p2c1', 'anotherCase', 'int');

ListenFor

ListenFor(); is similar to addTestCase();, the only difference is that listenFor(); allows you to set a callback function (that receives a sockEvent) bypassing the main sock.sockEvent listener (see Basic Sock Setup):

remove a listener by using stopListeningFor();.

package {
	
	// import sock classes
	import sock.Sock;
	import events.CommEvent;
	
	public class Main {
		
		// add the sock instance
		public var mySock:Sock = Sock.getInstance();
		
		public function Main():void {
						
			// a listener for setupComplete
			mySock.addEventListener(Sock.ON_SETUP_COMPLETE , onCommunicationSetup);
			
			// initialize sock (client)
			mySock.initialize('client1', 'client', '10.0.1.1', 4444, 5555);
		}
		
		// after the server has completed setup
		private function onCommunicationSetup(e:Event):void {
									
			// listen for 'running' from 'client2', parse as Boolean
			mySock.listenFor('client2', 'running', 'boolean', onRunningReceived);
			
			// listen for 'userName' from 'client5', parse as String
			mySock.listenFor('client5', 'userName', 'string', onNameReceived);
		}
		
		// the callback functions
		private function onRunningReceived(e.commEvent):void {
			
			//do something
			trace(e.caseValue);
		}
		private function onNameReceived(e.commEvent):void {
			
			//do something
			trace(e.caseValue);
		}
	}
}

Requests

Lets turn everything around, instead of sending lots of data through the server and using addTestCase(); or listenFor(); we can also save data locally (or let the server save everything) and use request(); to get data from other clients (or the server), as long as the client is running (and connected to the server) you will always get a result back, even if the client doesn't have the data you requested:

request(); is only executed once, once data is received back the request is considered granted, and gets removed from memory, request(); only works for direct application names, 'all' is not supported.

// request 'age' from 'client5', parse as String
mySock.request('client5', 'age', 'int', onAgeReceived);

// the callback function
private function onAgeReceived(e.commEvent):void {
	//do something
	trace(e.caseValue);
}

The CueList

If you attempt to send(); or request(); while the server/client communication is still setting up, or for some unknown reason disconnected, those calls are added to a cueList, the cueList is automatically sent out as soon as the connection has been established. The cueList can also be disabled by adding the following property before the initialize function:

mySock.cueListEnabled = false; 	// disables the cueList

// initialize sock
mySock.initialize('mySock', 'client', '10.0.1.1', 4444, 5555);

About the Server IP - Scan for Server

Sock requires you to set a server IP, but what happens if you're developing an application that should run for years to come. Imagine a scenario where both you applications are running on separate computers in a local network, eventually someone will reset a router (or some other network switch), all IPs will change and your apps will stop functioning, what's even worse is that you'll have to compile a new version of your applications (with a new server IP) each time this happens (or build an IP settings menu where you could manually change it at runtime)... sounds like a lot of work! That's why Sock includes the ability for clients to scan the local network for a server running at the specified ports, The client will first attempt to connect to the the specified IP, if this fails it'll scan the subnet (0-255), make sure you set the Servers IP (in the server initialize(); to "0.0.0.0" for this to work:

// CLIENT
// some devices, including the iPhone, do not have access to IP addresses so this will fail for those devices
myClient.autoDiscoverServer = true; 	// auto discover server when it's not available at the set IP

// initialize sock (setting the suggested server IP)
myClient.initialize('mySockClient', 'client', '10.0.1.1', 4444, 5555);

// SERVER
// initialize sock server (bind to 0.0.0.0 which will always be the devices/computers IP)
myServer.initialize('mySockServer', 'server', '0.0.0.0', 4444, 5555);

A complete list of properties/functions (with descriptions) is available in the ASDoc (located in the DOCS folder).

Top

Other Examples

Some other useful examples:

Sending/Receiving BitmapData (as a ByteArray) & Combining multiple variables into a single object

Imagine a scenario where a user would fill out a profile form and take a picture using a webcam, wouldn't it be nice if you could send/receive this data as a single object?, without the use of web-servers, databases, uploading/downloading etc. With Sock you can. By default Sock sends/receives data as a String, but there is also an object mode which allows you to send/receive complex data objects, simply set useObjects = true (for both server and client)

As an example the BitmapData (as ByteArray) is merged into a single object together with a name and a position (x and y). The ByteArray is automatically compressed using zlib (this can also be changed using the compressionMethod property).

Client setup (in this example the client will generate and send the bitmap):
package {
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;
	import flash.utils.Timer;
	
	import sock.Sock;
	import events.CommEvent;
	
	public class Main extends Sprite {
		
		public var client:Sock = Sock.getInstance();		// add the sock instance
		private var _testSprite:Sprite;						// the test sprite
		private var _objectCount:int = 0;					// counter (used for name string)
		
		public function Main():void {
			
			client.useObjects = true;						// use objects
			client.allowSave = false;						// disable saving (not needed)
			client.cueListEnabled = false;					// disable the cueList
			
			// a listener for setupComplete
			client.addEventListener(Sock.ON_SETUP_COMPLETE , onCommunicationSetup);
			
			// initialize sock (client)
			client.initialize('Client', 'client', '10.0.1.2', 4444, 5555);
		}
		
		// after the client has completed setup
		private function onCommunicationSetup(e:Event):void {
			
			// create the testSprite
			_testSprite = new Sprite();
			addChild(_testSprite);		
			
			// update & send the test Sprite once a second
			var timer:Timer = new Timer(100, 500);
			timer.addEventListener(TimerEvent.TIMER, timerTest);
			timer.start();
		}
		
		private function timerTest(e:TimerEvent = null):void {
						
			// update the sprite (fill with random color)
			_testSprite.graphics.clear();	// clear the previous fill
			_testSprite.graphics.beginFill(Math.random()*0xFFFFFF, 1);
			_testSprite.graphics.drawRect(0,0,100,100);
			_testSprite.graphics.endFill();
			
			// randomly position sprite
			_testSprite.x = Math.random()*stage.stageWidth - (_testSprite.width / 2);
			_testSprite.y = Math.random()*stage.stageHeight - (_testSprite.height / 2);
			
			// sprite to bitmapData
			var _bitmapData:BitmapData = new BitmapData(_testSprite.width, _testSprite.height, true);
			_bitmapData.draw(_testSprite);
			
			// bitmapData to ByteArray
			var _rect:Rectangle = new Rectangle(0,0,_testSprite.width,_testSprite.height);
			var _byteArray:ByteArray = _bitmapData.getPixels(_rect);
			
			// send position along with the bitmap
			var _point:Point = new Point(_testSprite.x, _testSprite.y);
			
			// just a name string example
			var _name:String = 'square_'+_objectCount;
			
			// create a new combined object to send everything as a single object
			var _combined:Object = new Object();
			_combined.bytes = _byteArray;
			_combined.position = _point;
			_combined.name = _name;
			
			client.send('combined', _combined);			
			
			// clear everything
			_rect = null;
			_byteArray = null;
			_point = null;
			
			// update the counter
			_objectCount++;
		}
	}
}
Server setup (in this example the server will receive and display the bitmap):
package {	
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Rectangle;
	import flash.net.NetworkInfo;
	import flash.utils.ByteArray;
	
	import sock.Sock;
	import events.CommEvent;
	
	public class Main extends Sprite {
		
		// add the sock instance
		public var server:Sock = Sock.getInstance();
		
		public function Main():void {
			
			server.useObjects = true;			// object mode
			//server.serverAutoEcho = false;		// there is no need to echo received data back to clients
			
			// a listener for every received case we're checking for	
			server.addEventListener(CommEvent.ON_UPDATED_CASE, onCommunicationUpdated);
			
			// a listener for setupComplete
			server.addEventListener(Sock.ON_SETUP_COMPLETE , onCommunicationSetup);
			
			// initialize sock (server)
			server.initialize('Server', 'server', '10.0.1.2', 4444, 5555);
		}
		
		// after the server has completed setup
		private function onCommunicationSetup(e:Event):void {
						
			// add the testCase (in this example the server also uses its client functionality)
			server.addTestCase('all', 'combined', 'object');
		}
		
		private function onCommunicationUpdated(e:CommEvent):void {
			
			// if a byteArray has been received
			if (e.caseName == 'combined') {
				
				// decode the byte array							
				var rect:Rectangle = new Rectangle(0,0,100,100);
				
				// the bitmap data
				var _bitmapData:BitmapData = new BitmapData(rect.width,rect.height, true);
				_bitmapData.setPixels(rect, e.caseValue.bytes);
				
				// the bitmap
				var image:Bitmap = new Bitmap(_bitmapData);
				image.name = e.caseValue.name;				// set the bitmap instance name
									
				// position image (based on received data)
				image.x = e.caseValue.position.x;
				image.y = e.caseValue.position.y;
				
				addChild(image);
			}
		}
	}
}
Top

Mobile Development

Sock has fully functional client support for Mobile development (iOS/Android), Since Mobile Apps only allow for a single stage/window the widget will be shown as a tab/overlay on the main stage, to allow for this to function correctly there is an additional property that needs to be set.


// add the main stage (needed for tabbed widget)
myClient.widget.setStage(stage);	

// initialize sock (server)
myClient.initialize('MobileClient', 'client', '10.0.1.2', 4444, 5555);

Things you should to know about mobile

Top

Log Messages

I've tried to keep the log messages as clear as they can be, but still giving enough insight into whats going on (for debugging purposes), the log messages have been color coded, grey messages are usually unimportant, black messages are normal priority, green are high priority of the good kind, and red are warning messages which require your attention.

Error Messages (console messages, will not show in widget log)

Important Messages:

Warning Messages:

Top

Extra information

Sock Server communication to it's clients

The Sock server really only does 1 thing, it takes an incoming data string (or object) and returns it to all connected clients, that's it, simple enough (this behavior can be overwritten by setting serverAutoEcho = false).

If client1 sends data to the server, client1 it will receive the data back immediately (since the server echoes to ALL clients), client1's own data is filtered out and discarded, however, if you'd like to see all data simply set logOwnData = true to see all received data in the log. (the exception of this is the built-in echo button in the client widget)

Socket Data

By default Sock sends all data as UTF strings ending with a '/', this socket data can be read/parsed using none AIR applications (they can connect to the server application using the specified IP and Ports), Sock also has the option to send data as objects (by setting useObjects = true). Choosing to send as object means AS3 will compress the objects making them harder (if not impossible) to be read by none AS3 applications. The default UTF string is composed in a certain way that allows easy interpretation while maintaining flexibility, the basic format is:

timeStamp_applicationName_caseName_value(s)

As soon as the data is parsed (on the receiving end), there will be a new timestamp added to the data, called receivedTime, this is useful in case you want to attempt to sync events across multiple applications, you can calculate the delay between sending and receiving and use this to update timed event in order to sync them across multiple applications. Be warned that doing these extra calculations also takes time, which will offset your delay, making it very hard (for example) to sync multiple video's to the exact frame.

Delay Calculation Example:
// this is where we get updates of cases we're testing for
private function onCommunicationUpdated(e:CommEvent):void {

	var delay:int = e.receiveTime - e.sendTime;
	trace(delay);
}

Overloading

Keep in mind that it takes time (both for the server and client(s)) to deal with the incoming/outgoing data, so try not to send too many data strings (or objects), I'd advice no more than 10 string messages, or 5 objects, per second running through the server at any given time. This number could be slightly higher when all applications (both server and client(s)) are running on the same machine). Always take a moment to consider if the Data you're about to send is actually needed and/or if it can be combined with other data.

Network, Firewalls & Ports

All the examples in this document are based on the premise that all applications run on the same local network, all the examples use local IP addresses. Using External IP adresses (servers/clients running on different networks) requires you to check your firewall settings (allow the sock applications to send/receive network data using the specified ports), and in case of a router, port forwarding (Portforward.com has lots of tutorials on the subject).

There are few unmentioned properties/functions available within Sock that I didn't cover in this manual, make sure you check out the ASDoc in your DOCS folder.

Thanks again for purchasing Sock - Simple AIR Sockets and good luck with your Sock Endeavors. For questions or bug-reports feel free to contact me...

Frank Douwes
contact@frankdouwes.com
www.frankdouwes.com

Top