Sign in or register

How to make a multi-client Flash Java server

ActionScript, Flash, Java

by nunof, 19:57 20-03-2008 (updated at 20:58 07-07-2010)

In this tutorial we make a Java server handle multi-client connections. The demonstration will be a chat application, using Flash for the client.

Introduction - Flash client and Java server

We're seeing an increasing use in online multimedia applications and Flash is an ideal candidate for this type of applications. It has the necessary features to provide a rich user interface, runnable in a browser.

In its most recent versions, Flash as gained the ability to work with sockets (and not only XMLSockets). Sockets are a communication end-point, used to establish a communication network between different parties. This has opened a lot of possibilities for Flash applications.

Java makes a good choice for a multi-client capable server. Both Flash and Java are closs-platform solutions, making them very portable as well as easily distributable.

Making a chat application with Flash and Java

In this tutorial we will explore these concepts and we'll make an application using Flash as the client and Java as a multi-client server. An example of a simple application that meets these characteristics is a chat application and we'll do just that.

Adobe has introduced a few security protections and for a Flash application to be able to connect to a server, it needs to know the policy used by that server to guarantee that access is granted to it. To handle this, we'll make a policy server in Java that could also be used separately for other servers that need Flash clients to connect to it.

Basically, this chat application needs 3 different parties: Flash chat client, Java chat server and Java policy server. This flow is described in the following picture.

Flash Multi-Client Java Server

You'll need ActionScript 3 for this tutorial. I'll use Adobe Flash CS3 Professional for developing the Flash client.

Making the Flash chat client

We'll start by making the Flash client. This will be composed of 2 separate files:

  • ChatClient.as: The ChatClient ActionScript class is responsible for communicating with the server
  • Chat.fla: The main Flash file, with the GUI for the chat and the code to use the client

Making the ChatClient class talk to the server

Let's start by creating our ChatClient class. This class will have the ability to send and receive simple messages from the server. For making this possible, it will need a socket and to know the server's IP and port. We'll also need to pass a TextField to the ChatClient class for it to be able to write the received messages.

The class definition and constructor should be as follow:

package {
    import flash.display.*;
    import flash.events.*;
    import flash.net.*;
    import flash.text.*;
 
    public class ChatClient extends Sprite {
        private var host:String;
        private var port:int;
        private var socket:Socket;
        private var chatArea:TextField;
 
        public function ChatClient(h:String, p:int, ca:TextField) {
            this.host = h;
            this.port = p;
            this.chatArea = ca;
        }
}

Now we can make a connect method and the related socket event handlers. To work with sockets in Flash we add event listeners to the socket that are called when something significant happens. We can do this using the code bellow (put it in the ChatClient class):

        public function connect():Boolean {
            this.socket = new Socket(this.host, this.port);
            this.socket.addEventListener(Event.CONNECT, socketConnect);
            this.socket.addEventListener(Event.CLOSE, socketClose);
            this.socket.addEventListener(IOErrorEvent.IO_ERROR, socketError);
            this.socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityError);
            this.socket.addEventListener(ProgressEvent.SOCKET_DATA, socketData);
 
            try {
                this.socket.connect(this.host, this.port);
            }
            catch (e:Error) {
                trace("Error on connect: " + e);
 
                return false;
            }
 
            return true;
        }
 
        private function socketConnect(event:Event):void {
            trace("Connected: " + event);
        }
 
        private function socketData(event:ProgressEvent):void {
            trace("Receiving data: " + event);
            receiveData(this.socket.readUTFBytes(this.socket.bytesAvailable));
        }
 
        private function socketClose(event:Event):void {
            trace("Connection closed: " + event);
            this.chatArea.appendText("Connection lost." + "n");
        }
 
        private function socketError(event:IOErrorEvent):void {
            trace("Socket error: " + event);
        }
 
        private function securityError(event:SecurityErrorEvent):void {
            trace("Security error: " + event);
        }

The connect method just creates a new socket with the host and port that was provided in the constructor. It adds event listeners for each significant event and tries to connect to the server.

Most of events are handled only for tracing purposes (which provide critical information when debugging a client-server application). The exceptions are the socketData and socketClose handlers. In the socketClose method we just write status information in the chat client. The socketData method reads all the bytes available in the socket buffer and calls the receiveData method which will be described bellow.

The only things that are missing are the methods for handling the received data and for sending messages to the server. We'll create a sendMessage method to write a message to the socket and a receiveData method to handle the data read in the socketData method. The code for these methods can be found bellow (this code belongs to the ChatClient class):

        public function sendMessage(msg:String):void {
            msg += "n";
 
            try {
                this.socket.writeUTFBytes(msg);
                this.socket.flush();
                trace("Message sent: " + msg);
            }
            catch(e:Error) {
                trace("Error sending data: " + e);
            }
        }
 
        private function receiveData(msg:String):void {
            trace("Message received: " + msg);
            this.chatArea.appendText(msg + "n");
        }

The received data is just written to the chat client. The sendMessage method appends a line break to the message before writing it and then flushes the socket. We'll not directly write the client's own message to its chat - we'll wait for the server to broadcast the message to all the clients and we'll only write it then.

Our ChatClient class is done.

Making the chat's GUI and Flash client

Now we need to setup the main Flash file with the GUI. It will be composed of an input text box, a button for sending the message and a text area to display the chat's messages.

Start by adding a new text field. Name it inputLine_txt and change its type to Input Text. Makes this long enough to hold a line of chat.

Now make a button and call it send_btn. This will be used to send the message (alternatively we will also use the Enter for this).

The only thing that's left to add is the text area where we'll display the chat. Add a new text field, call it chatArea_txt and change its type to Dynamic Text. Make sure Multiline is selected.

This setup is described in the following picture.

Flash Chat Client Setup

Now we need to add the necessary actions. Create a new layer, select the first frame and open the ActionScript panel.

Three things need to be done:

  1. Make a policy request to the server
  2. Create a ChatClient and connect to the server
  3. Handle the process of sending messages


Remember, and this is important, the connection to the server cannot be made if the Flash client hasn't received a policy string from the server confirming that it has access to the server. The Flash client will implicitly send a policy request to the server (<policy-file-request/>) and wait for the policy to be sent. We can also explicitly request a policy file from a specific location (this will be our approach).

After loading the policy file we'll create a new instance of ChatClient and connect to the server. We'll need to define the server's IP and port. In this example I will use a private address, because I have several computers in a LAN and I can test the application this way. You should change the IP to whatever is your server's IP and the same for the port. We'll use the same IP for the policy request, but on another port.

We'll then add event listeners for the mouse click on the Send button and also for key presses on the input text field to catch the Enter key. To send messages we define a function that checks to see if inputLine_txt is not empty, then it uses the ChatClient object to send a message to the server and also clears the text on inputLine_txt.

The code for accomplishing this is the following:

import ChatClient;
import flash.display.*;
 
var host:String = "192.168.1.12";
var chatPort:int = 5555;
var policyPort:int = chatPort + 1;
 
Security.loadPolicyFile("xmlsocket://" + host + ":" + policyPort);
var client:ChatClient = new ChatClient(host, chatPort, chatArea_txt);
client.connect();
 
send_btn.addEventListener(MouseEvent.CLICK, onSendClick);
inputLine_txt.addEventListener(KeyboardEvent.KEY_UP, onInputLineKey);
 
function sendMessage():void {
    if (inputLine_txt.text != "") {
        client.sendMessage(inputLine_txt.text);
        inputLine_txt.text = "";
    }
}
 
function onSendClick(e:MouseEvent):void {
    sendMessage();
}
 
function onInputLineKey(e:KeyboardEvent):void {
    if (e.keyCode == 13) { // ENTER was pressed
        sendMessage();
    }
}

And we're finished with the client. Now we need to make the server side of the chat application.

How to make a policy server with Java

As mentioned previously, Flash expects the server to handle policy requests. A policy is a XML containing the addresses which have access to the server and also to which ports they have access to. It's a security requirement that Adobe introduced in Flash and every server to which a Flash client wants to connect to with sockets must be prepared for this.

A policy server can be easily and quickly created using Java and you could use the solution we're going to build in other servers to which you need Flash applications to connect to.

The policy server will consist on two different classes:

  • PolicyServer: listens for clients' connections and creates PolicyServerConnections to handle them
  • PolicyServerConnection: reads policy requests from clients and writes the policy to them


I'll only explain and put here the code for the most important methods. This tutorial's files include all the code and all of it is well documented.

Let's start by defining the PolicyServer. This class will also contain the policy XML. In this case I setup the server to accept connections from all domains and granted access to all ports. You should be more restrictive and only give limited access.

public class PolicyServer extends Thread {
    public static final String POLICY_REQUEST = "<policy-file-request/>";
    public static final String POLICY_XML =
            "<?xml version="1.0"?>"
            + "<cross-domain-policy>"
            + "<allow-access-from domain="*" to-ports="*" />"
            + "</cross-domain-policy>";
 
    protected int port;
    protected ServerSocket serverSocket;
    protected boolean listening;
 
    /**
* Creates a new instance of PolicyServer.
*
* @param serverPort the port to be used by the server
*/
public PolicyServer(int serverPort) { this.port = serverPort; this.listening = false; }   /**
* Waits for clients' connections and handles them to a new PolicyServerConnection.
*/
public void run() { try { this.serverSocket = new ServerSocket(this.port); this.listening = true; debug("listening");   while (this.listening) { Socket socket = this.serverSocket.accept(); debug("client connection from " + socket.getRemoteSocketAddress()); PolicyServerConnection socketConnection = new PolicyServerConnection(socket); socketConnection.start(); }; } catch (Exception e) { debug("Exception (run): " + e.getMessage()); } } }

This is quite simple and doesn't require many explanations. We put some debugging messages which are very much needed to know what's going on under the hood. You should see the source code for the rest of the methods, but there isn't much more to it.

Handling Flash policy requests with Java

Now, let's define the PolicyServerConnection class. This class will read policy requests from clients and if they are valid, it sends the policy XML to them. It will receive a socket from the server and will open up a reader and a writer to be able to use the socket to talk to the client.

We'll make a readPolicyRequest method which will read a message from the socket, make sure it's a policy request and then calls the writePolicy method. This method writes the server's XML policy file and then closes the socket.

So, our PolicyServerConnection class should be something like this:

public class PolicyServerConnection extends Thread {
    protected Socket socket;
    protected BufferedReader socketIn;
    protected PrintWriter socketOut;
 
    /**
* Creates a new instance of PolicyServerConnection.
*
* @param socket client's socket connection
*/
public PolicyServerConnection(Socket socket) { this.socket = socket; }   /**
* Create a reader and writer for the socket and call readPolicyRequest.
*/
public void run() { try { this.socketIn = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); this.socketOut = new PrintWriter(this.socket.getOutputStream(), true); readPolicyRequest(); } catch (Exception e) { debug("Exception (run): " + e.getMessage()); } }   /**
* Reads a string from the client and if it is a policy request we write the policy, then we close the connection.
*/
protected void readPolicyRequest() { try { String request = read(); debug("client says '" + request + "'");   if (request.equals(PolicyServer.POLICY_REQUEST)) { writePolicy(); } } catch (Exception e) { debug("Exception (readPolicyRequest): " + e.getMessage()); } finalize(); }   /**
* Writes the policy of the server.
*/
protected void writePolicy() { try { this.socketOut.write(PolicyServer.POLICY_XML + "u0000"); this.socketOut.close(); debug("policy sent to client"); } catch (Exception e) { debug("Exception (writePolicy): " + e.getMessage()); } } }

Don't forget that's not the whole class. You should see the source code for the rest.

Our policy server is done. Quite simple, uh?

Making the Java chat server

The main server structure is similar to the policy server. We'll also use two classes for this:

  • ChatServer: listens for clients' connections and creates ChatServerConnection to handle them, adds and removes clients and broadcasts messages
  • ChatServerConnection: reads and writes chat messages to the clients


We'll start with the ChatServer class. You'll notice that it's very similar to the PolicyServer class. We'll add the remove method for when clients want to exit from the server and the writeToAll method for broadcasting messages.

Here is part of this class definition:

public class ChatServer extends Thread {
    protected ServerSocket socketServer;
    protected int port;
    protected boolean listening;
    protected Vector<ChatServerConnection> clientConnections;
 
    /**
* Creates a new instance of ChatServer.
*
* @param serverPort the port to be used by the server
*/
public ChatServer(int serverPort) { this.port = serverPort; this.clientConnections = new Vector<ChatServerConnection>(); this.listening = false; }   /**
* Listens for client conections and handles them to ChatServerConnections.
*/
public void run() { try { this.socketServer = new ServerSocket(this.port); this.listening = true; debug("listening");   while (listening) { Socket socket = this.socketServer.accept(); debug("client connection from " + socket.getRemoteSocketAddress()); ChatServerConnection socketConnection = new ChatServerConnection(socket, this); socketConnection.start(); this.clientConnections.add(socketConnection); }; } catch (Exception e) { debug(e.getMessage()); } }   /**
* Broadcasts a message to all the clients.
*
* @param msg the message to be sent
*/
public void writeToAll(String msg) { try { for (int i = 0; i < this.clientConnections.size(); i++) { ChatServerConnection client = this.clientConnections.get(i); client.write(msg); } debug("broadcast message '" + msg + "' was sent"); } catch (Exception e) { debug("Exception (writeToAll): " + e.getMessage()); } }   /**
* Removes a client from the server (it's expected that the client closes its own connection).
*
* @param remoteAddress the remote address of the client's socket connection
* @return true if the client was successfully removed
*/
public boolean remove(SocketAddress remoteAddress) { try { for (int i = 0; i < this.clientConnections.size(); i++) { ChatServerConnection client = this.clientConnections.get(i);   if (client.getRemoteAddress().equals(remoteAddress)) { this.clientConnections.remove(i); debug("client " + remoteAddress + " was removed"); writeToAll(remoteAddress + " has disconnected.");   return true; } } } catch (Exception e) { debug("Exception (remove): " + e.getMessage()); }   return false; } }

Very simple. When we remove a client we tell the others which client has disconnected. Also, it is the ChatServerConnection responsability to break the connection after being removed. We don't do this in the remove method.

In the ChatServerConnection class we simply wait for a client's message. We check to see if it equals "quit" which will be the command to exit from the chat. We also provide a write method to send a message to the client.

Here is the code for the ChatServerConnection class:

public class ChatServerConnection extends Thread {
    protected Socket socket;
    protected BufferedReader socketIn;
    protected PrintWriter socketOut;
    protected ChatServer server;
 
    /*
* Creates a new instance of ChatServerConnection.
*
* @param socket the client's socket connection
* @param server the server to each the client is connected
**/
public ChatServerConnection(Socket socket, ChatServer server) { this.socket = socket; this.server = server; }   /**
* Waits from messages from the client and then instructs the server to send the messages to all clients.
*/
public void run() { try { this.socketIn = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); this.socketOut = new PrintWriter(this.socket.getOutputStream(), true); this.server.writeToAll(this.getRemoteAddress() + " has connected."); String line = this.socketIn.readLine();   while (line != null) { debug("client says '" + line + "'");   // If it's a quit command, we remove the client from the server and exit if (line.compareToIgnoreCase("quit") == 0) { if (this.server.remove(this.getRemoteAddress())) { this.finalize(); return; } } this.server.writeToAll(this.getRemoteAddress() + ": " + line); line = this.socketIn.readLine(); } } catch (Exception e) { debug("Exception (run): " + e.getMessage()); } }   /**
* Sends a message to the connected party.
*
* @param msg the message to send
*/
public void write(String msg) { try { this.socketOut.write(msg + "u0000"); this.socketOut.flush(); } catch (Exception e) { debug("Exception (write): " + e.getMessage()); } } }

It's never too much to say that these are only the main methods. For the complete code see the source code.

The server is now done, but we'll spice up our server in the following chapter.

Setting up a GUI and test application

The final step in our server will be to tie everything together and provide a GUI so we can see what's happening. We'll need 2 more classes for this:

  • ChatServerGUI: providing a graphical interface for a more friendly testing experience
  • Main: the main class of the application, responsible for launching both the policy server and also the chat server


The ChatServerGUI is a very simple JFrame with a JLabel providing the number of connected clients and a JTextArea for displaying the debug messages.

I created a TimeTask to update the number of connected clients. This is easy to do but beyond the scope of this tutorial. You can see the source code for how to do this.

The ChatServerGUI only has a method: write. This method is used to write the debugging messages. It's defined as following:

    /**
* Writes a message to the text area of the form.
*
* @param msg the message to be written.
*/
public void write(String msg) { try { this.debugTextArea.getDocument().insertString(0, msg + "n", null); } catch (Exception e) { } }

There is not much more to this class. Now to the Main class. This class will launch both the policy and the chat server as well as the GUI.

This is the code for its main method:

    public static void main(String[] args) {
        try {
            int chatPort = 5555;
            int policyPort = chatPort + 1;
 
            for (int i = 0; i < args.length; i++) {
                if (i == 0) {
                    chatPort = Integer.parseInt(args[i]);
                }
 
                if (i == 1) {
                    policyPort = Integer.parseInt(args[i]);
                }
            }
            PolicyServer policyServer = new PolicyServer(policyPort);
            policyServer.start();
 
            ChatServer chatServer = new ChatServer(chatPort);
            chatServer.start();
 
            ChatServerGUI gui = new ChatServerGUI(chatServer);
            gui.setTitle("ChatServer");
            gui.setLocationRelativeTo(null);
            gui.setVisible(true);
        }
        catch (Exception e) {
            debug("Main", "Exception (main)" + e.getMessage());
        }
    }

That's pretty much it.

Testing the chat application

Finally we come to the fun part!

Start by executing the server application. This needs to be the first application running. Only then can the clients connect to it.

Now, our last fix. Because in my case I needed to test the application locally, I had to change Global Security Settings for my Flash player. This shouldn't be needed when running the Flash remotely. We need to give permissions to our Flash file.

The Flash Settings Manager is located on the web. Open your Flash Settings Manager. It should already be in the Global Security Settings tab. Now add a new trusted location for the location of your Flash file.

Flash Settings Manager

I know, this is a bummer! Also the message they give on the Global Security Settings don't make sense - we're using the latest features in ActionScript and Flash, not old methods!

Finally, start your clients and happy chatting!

Here is a picture of the server running.

Multi-Client Chat Java Server

Now, a picture of the chat client.

Flash Chat Client

Resources

Comments

17:19 30-09-2008jorgebucaran.com

Thanks for this tutorial. Very impressive.

01:02 01-12-2008pu-c

Heureka! I've been searching for hours now and finally, there is it! thanks thanks thanks

06:56 13-12-2008krishsal

jhio

07:00 13-12-2008krishsal

Hi,its working from Flash Compile time but its not working from the HTML file.. what could be the problem.. is XMLSockets work on the browser or else we should go for Javascript for the communication..

07:01 13-12-2008krishsal

Please help me this is very urgent.. My complete project depending upon the communication between flash and java.. thanks in advance..

11:58 13-12-2008ZappyAd

Great tutorial - but, I can't get the security fix working on vista 64b bit. I have set up the flash player settings as directed but still get the local files can't use sockets error. Do I need to do something else?

20:23 27-12-2008Hugo

How do you make a comment appliction... LIKE THIS lol, but seriously...

17:32 03-01-2009nunof

Thank you all for your comments.

@ krishsal: Sorry for the late response, make sure you did all the steps mentioned in this tutorial.

@ ZappyAd: I tested this on a Vista 64bit environment, so the OS should not be the problem. Are you sure you did all the steps mentioned in the tutorial?

@ Hugo: What do you mean? Please be more specific.

21:06 05-01-2009Rogier

Now THATS a tutorial!

18:20 07-01-2009Peter

Wow, this is awesome, thanks for the tutorial :)

17:22 08-01-2009Chad

Great tutorial! It's nice to see someone implement the policy server in Java as opposed to Perl/Python.

When I run a Flash app that uses sockets in Adobe Flash using Ctr+Enter, it connects perfectly. But when I try creating a socket connection when running it remotely, the server connects and disconnects in about 3 seconds. I currently have a call to the loadPolicyFile function with "http://ipaddress/crossdomain.xml" and host the file, but it doesn't work. So hopefully using Security.loadPolicyFile("xmlsocket://" + ipAddress + ":" + policyPort); and setting up a policy server will fix my problem.

* Does anyone else think this policy stuff is a bit over the edge? I can create a java applet that establishes a socket connection without a policy file.

07:07 14-01-2009Chad

Sweet... loading the policy file works great when I use the smlsocket:// request. Nice tutorial. =)

FYI... maybe this is common knowledge. But when you create an event handler for a ProgressEvent.SocketData, but you're only using mySocket.readUTF();... it is possible that there is a queue of messages waiting for you and you might have to read two or three strings each time the event handler is called.

In my situation, my server sends two string messages almost simultaneously after a user logs on. I figured the ProgressEvent handler would fire twice, but it doesn't. I had to do:

while (mySocket.dataAvailable > 0) {
var msg:String = mySocket.readUTF();
...
}

04:28 15-01-2009James

In the Chat Server Connection Class at the end of the file you have "this.socketOut.write(msg + "u0000"); ". What is the purpose of the u0000?

I've been having trouble with my socket server, if I send nonsense I correctly receive the "malformed policy file" warning, but If I send the policy file you have listed above, my client times out after 3 seconds while "waiting for socket policy file".

My guess is I'm missing a terminator at the end of the policy file.

16:30 19-01-2009AndyCook

Hi,

This tutorial looks great. I am trying to get the files you provided working on my server and when I try to compile the java classes using "javac FileName.java", I get errors saying something like:

PolicyServerConnection.java:65: cannot find symbol
symbol : variable PolicyServer
location: class chatserver.PolicyServerConnection
if (request.equals(PolicyServer.POLICY_REQUEST)) {

Is there a certain order you have to compile the files in? Or maybe I am just compiling everything wrong. Thanks a lot for your help

07:15 20-01-2009Chad

Hmmm... an interesting problem. I set up the server and client, and it works great using a browsers from a Windows PC or a system running Ubuntu... but it won't create a connection from a Mac running OS X.

The client sends the Policy request to the server, the server replies and clears the policy connection. But then the real connection never establishes itself.

Anyone else have this problem?

10:15 02-02-2009MOHAMMAD

Thanks for this tutorial. it's great and helps a lot. i hop Adobe doesn't comes up with new flash Player :)
any way i need to change my server program . I looking forward for your new tutorials.

11:50 11-03-2009Filip

I would just like to say, great job & thx! Spent quite some time trying to pull this of on my own and then I find this fantastic tutorial :)

08:45 05-07-2009Rick_Winscot

With regard to the Mac OS X problem... if you are setting up your policy server on port 843 or any port below 1024 - these are considered 'privileged ports.' Any bind will fail unless the process is started as root. Workarounds include but are not limited to: commons-daemon, jsvc, some fancy scripts, chown, or pixie dust.

20:41 13-08-2009Michael

Hi, I have written the as you have it here and there is only one error int the next line:

String request = read();

who belongs the read() method to? I thought it belongs to the instance socketIn but this hasn't this method.

Thanks in advance and great tutorial, i have been looking for one of this kind for to long.

22:44 14-08-2009nunof

The read() method belongs to the PolicyServerConnection class. It was omitted for brevity.

You can get the complete source code at http://www.broculos.net/files/articles/FlashJavaChat/FlashJavaChat.rar.

00:23 16-08-2009Durnus

If I'm not mistaken, it's a null character. See wikipedia here: http://en.wikipedia.org/wiki/Null_character

Flash requires all data from sockets to be ended in a null character, so that's probably why it's there.

>By: James
>In the Chat Server Connection Class at the end of >the file you have "this.socketOut.write(msg + >"u0000"); ". What is the purpose of the u0000?

02:52 25-08-2009Brokkoli

thank you. great work :)

16:07 28-08-2009JuniorL

Muito bom, valew ae!
abraços...

15:56 18-09-2009david

hello. I would like to ask you for help. I am looking for a live chat support. Example: i have approx. 150 operators. Each operator needs to have its own chat room (window chat) so other users can directly communicate with him. So if i have 150 operators i need 150 different chats windows (rooms). Do you think this is possible deploy using flash and xml socket server? thank you very much for your help! david

19:00 19-09-2009nunof

Hi David,

A Flash and Java solution should be able to deal with that.

But you can easily make a test scenario, by downloading the source code of this tutorial and making some adjustments to your needs.

12:28 26-09-2009Eero

Hi!
I try to do something similar on Mac on localhost and it seems that if I put the swf in trusted location it did not need any policy file at all but outside trusted location I get request for policy file, send it and then connection just times out and I get security violation error.
Now I tried Your application (made some minor changes for working on Mac) and same problem - from outside trusted location swf don't get policy file and no connection.

03:48 28-09-2009Shenglong

hi great tutorial, been looking for one like this for ages :)

just one question, how would i assign unique id numbers to all the clients who connect and then remove when they disconnect ?

13:11 28-09-2009Eero

Hi.
I read from official documentation that there is some differences on localhost but as I now understand Flash player don't accept policy file on localhost.

15:11 10-10-2009Cander

Thank you!



http://javaforums.smfforfree3.com/index.php

00:15 20-10-2009Ric01

Hey nunof! Great tutorial! This is awesome! Thank you for posting it!

Question: Is this meant to only be used as a model for other programmers who are looking to make their own chat servers and clients, or can this code that you have written and provided here be freely used for any purpose? In other words, if I'm making my own chat program, do you mind if I use and modify the Flash/Actionscript and Java code that you have here?

Thanks!

-Ric

08:36 20-10-2009nunof

Hi Ric,

Thanks for the comments.

You are free to do with the code whatever you want.

Good luck!

15:26 20-10-2009Ric01

Thank you, nunof!

You've helped me out a lot!

Best,
Ric

04:40 27-10-2009Ric01

Hey again, nunof!

Another question for you: Any idea how to automatically make the dynamic text field scroll down when it's full of text? I've discovered that when you add a new line of text after filling up the text box, it jumps back up to the top line and makes it so the bottom-most text is not visible. Then you need to scroll down by clicking and dragging downward within the dynamic text box area.

Thanks!
-Ric

08:36 27-10-2009nunof

Hi Ric,

Sorry, I don't know. I haven't developed on Flash for some time.

Maybe it's one of the properties of the text field.

21:39 27-10-2009Ric01

Good news! I've got it working!

I added one line to your receiveData function in ChatClient.as.

private function receiveData(msg:String):void {
trace("Message received: " + msg);
this.chatArea.appendText(msg + "\n");
this.chatArea.scrollV = this.chatArea.maxScrollV;// This is the new line that I added - This will scroll the text down automatically to the bottommost line as new text is added.
}

Hopefully someone else can benefit from this addition!

-Ric

08:37 28-10-2009nunof

Great!

Thanks for your addition.

15:12 25-11-2009Omni

Great tutorial! Made it work.
One question though, is it possible to send objects instead of just a string?

That way i can sent multiple variables at once.

16:29 25-11-2009nunof

@Omni: For that purpose you can try serializing objects before sending them and then deserializing them when receiving.

But you have to use the same technique to serialize/deserialize on both ends, of course.

20:21 26-11-2009Omni

heh, that's the part where i got stuck, im not sure how to serialize them so they can read each other. when i just send the flash object over the server gets the error "invalid stream header: 0609686F". There is so little info on google about flash/java socket objects im starting to think it's not the common way to handle this.

21:43 26-11-2009Omni

I made it work! was using ObjectOutputStream and bjectInputStream, but flash sends it as a string(serialized that is). Finally!

22:53 26-11-2009nunof

Glad that you figured it out!

17:18 17-01-2010Alexander

Great tutorial, but there is a few thing I dont understand!

First:
It looks like the client are trying login on twice (both on your picture under "Here is a picture of the server running." and in real life at my computer. One of the logons work and the other is aborted.
I guess it aint a good practice to logon dobble.

Second:
At your function "writeToAllclient" I tried puting in "client.write("Count connections: " + this.clientConnections.size() );" to see how many connections the server got. I suspected that the server and I didnt agree.
When I connected two clients the server wrote "Count connections: 4" - wich is wrong.

I think that there is some problem with taht server and the counting of connections.

22:36 03-02-2010Alexander

It looks like you are making a double socket-connection:
this.socket = new Socket(this.host, this.port);
this.socket.connect(this.host, this.port);

I think the first should be:
this.socket = new Socket();

Thx for a good tutorial.

22:48 03-02-2010nunof

I think you are right.

Thank you very much for noticing that!

15:34 04-02-2010Alexander

I think that you cant expect clients nicely to say 'quit' before loosing connection to the server.
So I suggest to remake the run-function in ChatServerConnection to:
public void run() {
try {
socketIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
socketOut = new PrintWriter(socket.getOutputStream(), true);
server.writeToAll(getRemoteAddress() + " has connected.");
String line = socketIn.readLine();

while (line != null) {
debug("client says '" + line + "'");
server.writeToAll(getRemoteAddress() + ": " + line);
line = socketIn.readLine();
}
} catch (Exception e) {
debug("Exception (run): " + e.getMessage());
} finally {
try {
server.remove(getRemoteAddress());
} catch (Exception e) {
debug("Exception (run): " + e.getMessage());
}
finalize();
}
}

I think it would make it, so if clients drop the connection to the ChatServer then they will be removed from the list automatically.

15:55 04-02-2010nunof

Hi Alexander, thanks for your input again.

I haven't tried what you suggested yet, but I don't think it will work that way.

To be able to detect a lost connection from a client, I think you will need to create a mechanism where it will ping the client every few seconds and see if it responds back and remove the connection when you don't get a response after a specific timeout.

12:58 13-02-2010sabereh

hi,Great tutorial!
I'v a question about this.
i undrestood how send a public message by your tutorial,but how can i send a private message to spessial person ?
tnx again

10:08 14-02-2010nunof

Then you need to keep track of private chat sessions between users.

You'll need to create more commands to initiate and leave private chat conversations and keep a channel open only between those users.

19:33 14-02-2010sabereh

hi
tnx for reply, but i need more guide,
how can i do : " keep a channel open only between those users" ?

20:49 14-02-2010nunof

I haven't researched that but obviously the server will have to keep track of what private conversations are going on and the client will need an additional window for each private conversation.

Each time the client sends a message it needs to inform the server to who it is meant (if it's a private one). Then the server just sends it to that destination.

It's basically adding more layers to this demo, some more commands that the server will need to interpret and methods for private messaging (identifying the sender/receiver).

If you know how to program and work with Java and Flash and understand this tutorial, it shouldn't be that hard to build something more on top of this.

12:07 16-02-2010sabereh

thank you so much.

14:14 27-02-2010salrod

Hi nunof, great tutorial!!
i have a question to Omni... how you send the objects in flash? an another question, how you read in Java, those objects?
Thank you very much

10:38 28-02-2010Sabereh

hi nunof,i'm trying to put this line in block if ,becouse i need to display and send "abc" in flash:
this.server.writeToAll(this.getRemoteAddress() + "abc"); (in chatserverconection.java)
but i can't.
then next ,trying to use public variable "u", and assign value to "u" in "block if" ,
and change this line to :
if(...)
{
u = "abc";
}
this.server.writeToAll(this.getRemoteAddress() + u);
but ,this not work ,and send null to flash.
can u help me plz?
best regrds.

10:55 28-02-2010nunof

Hi Sabereh,

What do you mean by "block if"?

Where are you trying to put this code?

11:32 28-02-2010Sabereh

hi,tanx for your reply ,
i change your code to :
public String u;

public void run() {
try {
this.socketIn = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
this.socketOut = new PrintWriter(this.socket.getOutputStream(), true);

this.server.writeToAll(this.getRemoteAddress() + "conect");


line =this.socketIn.readLine();


if (line != null) {

if (line.startsWith("HELOS"))
{

u ="~HI~2";

}
this.server.writeToAll(this.getRemoteAddress() +u); //IT SEND NULL TO DEBUG
// If it's a quit command, we remove the client from the server and exit
if (line.compareToIgnoreCase("\\quit") == 0) {
if (this.server.remove(this.getRemoteAddress())) {
this.finalize();
return;
}
}
}
}
TANX AGAIN .

11:51 28-02-2010nunof

First, you removed the while loop, so you will only get one message from the client.

Also, the "u" string will only have something if the client says "HELOS".

You can use the "debug" method to write some debugging information on the server side.

12:19 28-02-2010Sabereh

hi,
yes , you'r right .but i have to use this cod.becouse i need keep track conversation , but i couldn't do it in java code,then i manage private chat in flash by send and recieve flags.
in dbug ,"HELOS" recieved .but dont send to flash :~HI~2" .
what's your idea for access "u" ,in out of IF condition?
thank you

14:50 28-02-2010nunof

What does the client receive?

17:29 28-02-2010Sabereh

hi ,i so thank you for your replys .
this problem was solved.I had a mistake to typing "HELOS".I so sorry.
but i have an another problem again...
next handshaking above , i should to send a message in flash chat ... but conection closed and so it dosent send .it 's output:

ChatServer (5555): broadcast message '/127.0.0.1:43782~HI~200' was sent
ChatServer (5555): broadcast message '/127.0.0.1:43782conect' was sent
ChatServer (5555): client connection from /127.0.0.1:43782
PolicyServerConnection (/127.0.0.1:54857): connection closed
PolicyServerConnection (/127.0.0.1:54857): policy sent to client
PolicyServerConnection (/127.0.0.1:54857): client says ''

tanx

18:21 28-02-2010nunof

Doesn't that happen because you removed the while loop in the run method?

14:14 01-03-2010Sabereh

hi nunof ,
thanks alot for noticing that.
best regards

16:46 01-03-2010Rene

Hello, nice tutorial. Everything works fine... but I had troubles to compile it. Maybe some others had troubles also.

Here's what I found to make it work:

javac -d . *.java
java chatserver.Main

Leave a comment

RSS article feed RSS article feed

© 2007-2010 Coconuts. Contact us.