socketBridge: Flash - Javascript Socket Bridge
Update: 26 Aug 2008
Have updated the SWF and Haxe sources. Due to a rookie error I had forgot to flush Flash’s output buffers when sending the message to the server. This was causing issues on some player versions.
I’ve been looking at a few flash - javascript socket server bridges recently with the hope of using one to allow me to speak to my Arduino via javascript. I’ve ended up writing my own one here - it’s usually more fun that way, and I can get it to do exactly what I need. However, there’s a couple of good options out there that you might
also want to check out:
SocketJS - Seems to work well and has a nice low file size. The only problem I had with it is that is does not easily allow for object oriented javascript as all of the callbacks are done at the global scope.
jssockets - Nice object oriented interface available here although the function called when the SWF is loaded is still in the global scope. Also this project uses Flex which makes the files size around 120+ KB, a little too large when compared with SocketJS’s ~3KB.
My version is called socketBridge, I think it does most of the things I wanted, mainly allowing for use of object oriented javascript throughout. I also avoided using Flex which kept the filesize nice and low. I’m still not 100% sure about the code quality as this is my first Flash project, prior to this I’d not written any ActionScript at all. To be honest I didn’t even write any here, it was all done using haxe.
I ran into a few issues with Flash’s ExternalInterface, it seems lock up the SWF whilst waiting for the javascript callbacks to return. This posed a bit of a problem when I wanted to do something like have the SWF tell the javascript that it’s loaded and then have that same callback ask the SWF to open a socket connection. The SWF wouldn’t be able to hear my javascript as it had halted whilst waiting for the loaded callback to return!
I found a way around this by wrapping all the callbacks from Flash in a setTimeout method. This effectively opens a new javascript thread and as such straight away returns the original callback. I picked up this tip here.
Feel free to download the bridge swf or alternatively grab the haxe source. It should all be pretty straight forward from a client side point of view.
If this is your first attempt at communicating with a Flash socket server then you may run into a few pitfalls. Flash seems to have some varying security policies depending on the player version, I won’t pretend to understand them all here but Adobe does a pretty good job here.
SocketBridge - connect to your server
Download
- socketBridge: Flash - Javascript Socket Bridge SWF
- socketBridge: Flash - Javascript Socket Bridge SRC
Usage
Include the SWF in your page using something like swfobject.
so = new SWFObject("/path/to/socket_bridge.swf", "socketBridge", "400", "300", "9", "#ffffff");
so.addParam("allowscriptaccess", "always");
so.write("flashcontent");
The flash movie outputs messages such as what’s being sent and received, you can pick these up with the javascript callbacks though. Best just to get rid of the swf from the HTML page.
#socketBridge {position:absolute;top:-1000px;}
Methods
connect(host, port)
Opens a new socket connection.
var socket = document.getElementById("socketBridge");
socket.connect("localhost", "5000");
write(msg)
Sends a string to the current socket server connection.
socket.write("Hello socket server");
close()
Closes the current socket server connection.
socket.clsoe();
Callbacks
The socket bridge SWF communicates to a series of javascript callbacks.
By default all callbacks are made to the global scope, however the socket bridge SWF can be provided with an optional scope flash var when being included. If used this should be a javascript namespace or object that enapsulates the callback functions the socket bridge uses.
so.addVariable("scope", "myObject");
// Callbacks will now all be in the scope of myObject
// myObject.callback()
loaded()
Called once the SWF has been loaded, after this call it is safe to open a socket connection.
connected()
Called once a connection with a socket server has been successfully estabished.
disconnected()
Called when the cuurent connection is closed.
ioError(error_message)
Called when an IO Error occurs with the current connection.
securityError(error_message)
Called when a security Error occurs with the current connection. Flash seems to have varying security policies depending on the player version.
receive(message)
Called when a new message is received from a socket server
Example
Below is an example of setting up a scoped object to communicate with the socket bridge
// Object to encapsulate callbacks and communicate with socket bridge
var myObject = {
// Socket bridge callback functions
loaded : function() {
// SWF loaded OK, ready to connect
this.flashMovie = document.getElementById("flashMovie");
this.connect();
},
connected : function() {
// Code that you want executing after a succesful connection
},
disconnected : function() {
// Code that you want executing after a disconnection
},
ioError: function(msg) {
// Code that you want executing after an IO error
},
securityError: function(msg) {
// Code that you want executing after a security erro
},
receive: function(msg) {
// Code that you want executing after we've received some data
alert("Received from the socket server: " + msg);
},
// Functions to communicate with socket bridge
connect : function(server, port) {
// Connect to server
// EG: this.flashMovie.connect("localhost", "5001");
this.flashMovie.connect(server, port);
},
close : function() {
this.flashMovie.close()
},
write : function(msg) {
this.flashMovie.write(msg);
}
};
// Include socket bridge SWF
so = new SWFObject("/path/to/socket_bridge.swf", "socketBridge", "400", "300", "9", "#ffffff");
so.addParam("allowscriptaccess", "always");
so.addVariable("scope", "myObject");
so.write("flashcontent");
Bryan Buschmann
on 22 Aug 2008 at 5:34 pmI’m happy to see that people are still looking into this bridging solution as I’ve been searching for a sockets based solution for a project I’m involved with. However, it seems that no one has come to terms with the new security requirements of Flash and sockets.
Are you currently working on what needs to be done in order to process the file-policy-request returns on the client side? I’ve been trying to decipher the actual process and unfortunately can’t come to any specific answers. I’m using my custom socket server, the test scripts that were in the initial announcement, and various client scripts.
I don’t know what I’m missing here. I have a policy server running and visible, its processing requests and sending out policy but for some reason, nothing is working except the older “non-secure” clients.
I would love to get some additional brainpower on this issue.
bit
on 24 Aug 2008 at 9:06 amI’m having the same problem as the comment above me, and your example isn’t working. for your domains’ IP address (208.43.45.224) on port 80, I get ” Security Error: Error #2048: Security sandbox violation: http://matthaynes.net/flash/socket_bridge.swf cannot load data from 208.43.45.224:80.” Did you actually check this code before you published it?? why isn’t this working?
matth
on 25 Aug 2008 at 8:23 pmI find the Flash security policies pretty confusing too. I’m not a Flash developer and haven’t got much experience with this stuff prior to developing the socketBridge app. As far as I know though, the Flash player itself deals with all the processing of policy-request files, i.e. you do not have to code any handling into your application.
The way I got this working was to host a Flash master socket server on port 843, the newer Flash players will call on this first to get the policy-file. Basically my master server just serves up the following file:
<?xml version="1.0" encoding="UTF-8"?'> <cross-domain-policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.adobe.com/xml/schemas/PolicyFileSocket.xsd"> <allow-access-from domain="*" to-ports="*" secure="false" /> <site-control permitted-cross-domain-policies="master-only" /> </cross-domain-policy>I then host my actual socket server on whatever port I want and handle the socketBridge requests from there. Think the process goes something like this, Flash Player connects to master server on port 843 and retrieves the policy file, based on the permissions defines it then connects to the server you requested in the socketBridge app.
As I say I’m no expert at this, but this is the idea I got from reading the adobe post on socket policy files.
@bit - I’m not actually hosting a socket server on my domain here so you won’t be able to use the socketBridge to connect to it :) The socketBridge application is simply a client that allows you to talk to a socket server via javascript. You will still need to develop and host your own socket server.
Tom
on 24 Oct 2008 at 8:25 pmI wrote a small python policy server for the people that just don’t want to write it :)
Selçuk YAZAR
on 30 Oct 2008 at 7:39 amHi,
thanks for the code and samples, but i tried all thing but it didn’t work.i wrote my socket server using c#. it’s listen 9000 port and i have corssdomain.xml file and i added the line “loadPolicyFile” into hx code. But it’s not working. any other suggestion.
thanks in advance.
ionel
on 12 Nov 2008 at 9:00 amThe way you call the callbacks using setTimeout is bound for failure: no quote escape for the string you pass to setTimeout. While it can be easily fixed i don’t think it would be very performant. A solution would be just calling the callbacks as usual and do setTimeout if necessary in the javascript code.
Flash socket bridge with haxe « ionel’s coderlog
on 28 Nov 2008 at 11:24 pm[...] of solutions for making a bridge to use the flash sockets (flash.net.Socket) in javascript, notably socketBridge and jssockets. But I didn’t like the way they made you write your client code: because you [...]