Communicating with Java over a Socket via Actionscript 3
The goal here is to get you communicating. I will provide you with an explanation of what I’m doing without exhausting what is happening. I hope to put you in a position to experiment with your own ideas, because really… that’s the best way to learn.
So the first thing we should ask ourselves is… what is really going on? I’m sure you know that you’re trying to talk to Java and you know that you want to do it using Actionscript 3, but I’m going to assume that you are reading this more because you don’t know how to communicate your own Java application back to Actionscript. Maybe you don’t know Java at all and don’t really have a reason to, but a way to communicate with your own application that can integrate multiple users in a more real time way may be a good reason, although we will not introduce multi-threading, and therefore multi-user support, until the second article. So… maybe I should should just get on with it…
If you are not familiar with Java you will probably need to get the sdk and learn how to compile a Java program. You can find that info here [insert link to tutorial on compiling java]
Basically this is what is going to be happening. Actionscript opens up a Socket to a port at some location. On that port at that location a program is listening and waiting to handle that connection. Actionscript will listen to that Socket for messages from the program as well as use that Socket to write messages back to the program. The program, which we will write in Java, will use a ServerSocket to communicate with the Socket.
With most of the crappy details removed that is what is going to happen in our system. I am going to step through how we get it running on both ends.
For the sake of conversation we are going to make ’something’. It will not be useful for anything really, it’s just a simple example to get you going on your own two feet. We will make two programs a Java program we will call DemoServer and an Actionscript program we will call DemoClient. You will be able to send messages to DemoServer using DemoClient. In this first article the DemoServer will simply just send you a reply that it received the message. In the second article we will convert DemoServer into a multi-threaded system that can handle multiple clients. In that article the DemoServer would relay the message you send to all other clients that are connected to it creating a simple Chat system.
Actionscript
We are going to do some pretty basic stuff here. So the first thing we need to decide on is where the Java program is going to live. I’m going to assume that you are just testing this locally making the host localhost. I chose 5555 for the port, this is just a random decision and can be changed to whatever you’d like (minus general operating system constraints).
Now we will write the DemoClient class. For the sake of simplicity it will have 3 properties host, port, and socket. When DemoClient is created we set it’s host and port properties and then attempt to connect to that location with a Socket.
The DemoClient class
package
{
import flash.display.Sprite;
import flash.net.Socket;
public class DemoClient extends Sprite
{
private var host:String;
private var port:int;
private var socket:Socket;
public function DemoClient()
{
host = "localhost";
port = 5555;
connect();
}
private function connect():void
{
// socket connection code goes here
}
}
}
Now we need to connect. All we do is create a new Socket, begin listening to it for status events, and then try to connect at our location host, port. We will listen for 3 different kinds of status events from the Socket: when it has connected, when it has closed, and when it has run into an error. In our example we will not do anything other then trace a message when the socket has closed or run into an error.
Some additions to the DemoClient class
import flash.events.Event;
import flash.events.IOErrorEvent;
private function connect():void
{
socket = new Socket();
socket.addEventListener(Event.CONNECT, socketConnect);
socket.addEventListener(Event.CLOSE, socketClose);
socket.addEventListener(IOErrorEvent.IO_ERROR, socketError );
try
{
socket.connect( host, port );
}
catch ( e:Error )
{
}
}
Once we are connected to the Socket we can begin sending messages to the DemoServer. So let us do precisely that. We will wait until we are connected, and then send one message to the server. We send the message in the following format cmd;message\n. The cmd part of the message lets the DemoServer know what to do with the message, the message is obviously the message, and the \n is how the DemoServer knows our message has ended. If we didn’t the server would just wait and do nothing.
We introduce 4 methods to DemoClient. The sendMessage method prepares the message to be sent to the server and then writes it to the socket. The socketConnect method just writes a message to the server, we also begin listening for data from the server in this method. The receiveMessage method handles a message that has been sent from the server. The socketData method receives data from the server and passes it along to the receiveMessage method in the format it is expecting.
More additions to the DemoClient class
import flash.events.ProgressEvent;
private function socketConnect( event:Event ):void
{
socket.addEventListener( ProgressEvent.SOCKET_DATA, socketData );
sendMessage( "Hello DemoServer" );
}
private function sendMessage( message:String ):void
{
message = "message;" + message + "n";
if ( socket && socket.connected )
socket.writeUTFBytes( message );
}
private function socketData( event:ProgressEvent ):void
{
receiveMessage( socket.readUTFBytes( socket.bytesAvailable ) );
}
private function receiveMessage( message:String ):void
{
trace( message );
}
The Actionscript portion of our work is now done. Let’s move on to the Java.
Java
Believe it or not the Java program is really simple too. We already know that we are hosting this locally on port 5555.
Let’s create the DemoServer. First we need to decide how it will be run. We will have a main method which creates a new instance
of DemoServer, the server is then started using it’s start method. Here we create the ServerSocket for the server and then begin running the server.
DemoServer class
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class DemoServer
{
private ServerSocket server;
private Socket client;
private BufferedReader in;
private PrintWriter out;
public void start()
{
// starter code here
}
public static void main( String[] args )
{
try
{
DemoServer server = new DemoServer();
server.start();
} catch ( Exception e )
{
e.printStackTrace();
System.exit( 0 );
}
}
}
You can note here that DemoServer has 4 properties: The server which the program uses to communicate to the clients who connect to it. The client socket who is currently connected to it. The in is the way we receive messages from the client. The out is how we send messages to the client.
Our start method calls two other methods. First create is called which creates the socket server. Then the run method is called and is where the magic happens.
Additions to DemoServer
public void start()
{
create();
run();
}
private void create()
{
try
{
server = new ServerSocket( 5555 );
}
catch ( Exception e )
{
e.printStackTrace();
System.exit( 0 );
}
}
Our run method is a little more involved. Essentially this is what we are doing. First we wait until a client has connected then we grab their input stream and their output stream. Then we continually try to read messages the client is sending us. Once we have a message we print it to the console, and then notify the client that we have received the message.
The run method in DemoServer
private void run()
{
try
{
client = server.accept();
in = new BufferedReader( new InputStreamReader( client.getInputStreamReader() ) );
out = new PrintWriter( client.getOutputStream() );
} catch ( Exception e )
{
e.printStackTrace();
System.exit( 0 );
}
String line;
while ( true )
{
try
{
line = in.readLine();
if ( line != null )
{
System.out.println( "Line received: " + line );
out.write( "Line was received." );
out.flush();
}
}
catch ( Exception e )
{
e.printStackTrace();
System.exit( 0 );
}
}
}
Note that the line out.flush(); is necessary because you write to the clients output stream, but you eventually have to commit it to the client so that they can receive it.
And that is pretty much it. I left some methods out of both classes because they are completely irrelevant or just don’t matter too much (although matter enough that they are required), you can check these methods out along with the full code files that are attached to this post. I am going to clean this up, but I want to get some early feedback.
In the next article on this I will be turning DemoServer into a multi-threaded system and make the all around application more resemble a chat room.
January 10th, 2008 at 6:52 am
hi
so i think i am rdy for next article
in fact, i am triing to make simple telnet in as3, especcially connection to smtp server.
if u coud write some example or finish this article (and show how it works in flash), maybe some .flv .swf it ll be gr8
January 14th, 2008 at 3:21 pm
This is a very good tutorial.
I’m also very interested in how we go about handling multiple clients.
January 25th, 2008 at 1:29 am
it’s very interesting! thank you!
February 2nd, 2008 at 4:22 pm
Hi,
In your code you are calling server.start(), isn’t it just start()? You are defining a start() method of the DemoServer class, you have both server and client socket varibles, but you call a server.start() method. I don’t know if there is such one but how does the DemoServer.start() method gets called then?
public class DemoServer
{
private ServerSocket server;
private Socket client;
private BufferedReader in;
private PrintWriter out;
public void start()
{
// starter code here
}
public static void main( String[] args )
{
try
{
DemoServer server = new DemoServer();
server.start();
//start()
February 12th, 2008 at 3:16 pm
Has actions script 3 dumped xml sockets, and uses standard bytes? Been a while since I toyed with sockets in as.