import java.awt.event.*;
import java.util.*;
import java.awt.*;
import java.io.*;
import java.net.*;
/**
*
* CommServer
* <BR><BR>
* Generic Flash Communication Server. All communications sent and received
* are (must be) terminated with a null character ('\0') consistent with
* the way Flash does socket communications. Any client which uses this
* protocol should also work.
* <BR><BR>
* The server accepts messages from connected clients and broadcasts (verbatim)
* those messages to all connected clients. When clients connect or disconnect
* the server also broadcasts the number of clients via a NUMCLIENTS tag.
*
* Usage: java CommServer [port]
*
* @author Derek Clayton derek_clayton@iceinc.com
* @version 1.0.1
*/
public class CommServer {
private Vector clients = new Vector(); // a list of all connected clients
ServerSocket server; // the server
/**
* Constructor for the CommServer. Begins the start server process.
* @param port Port number the server should listen to for connections.
*/
public CommServer(int port) {
startServer(port);
}
/**
* Starts the server and listens for connections.
* @param port Port number the server should listen to for connections.
*/
private void startServer(int port) {
writeActivity("Attempting to Start Server");
try {
// --- create a new server
server = new ServerSocket(port);
writeActivity("Server Started on Port: " + port);
// --- while the server is active...
while(true) {
// --- ...listen for new client connections
Socket socket = server.accept();
CSClient client = new CSClient(this, socket);
writeActivity(client.getIP() + " connected to the server.");
// --- add the new client to our client list
clients.addElement(client);
// --- start the client thread
client.start();
// --- broadcast the new number of clients
broadcastMessage("<NUMCLIENTS>" + clients.size()
+ "</NUMCLIENTS>");
}
} catch(IOException ioe) {
writeActivity("Server Error...Stopping Server");
// kill this server
killServer();
}
}
/**
* Broadcasts a message too all connected clients. Messages are terminated
* with a null character.
* @param message The message to broadcast.
*/
public synchronized void broadcastMessage(String message) {
// --- add the null character to the message
message += '\0';
// --- enumerate through the clients and send each the message
Enumeration enum = clients.elements();
while (enum.hasMoreElements()) {
CSClient client = (CSClient)enum.nextElement();
client.send(message);
}
}
/**
* Removes clients from the client list.
* @param client The CSClient to remove.
*/
public void removeClient(CSClient client) {
writeActivity(client.getIP() + " has left the server.");
// --- remove the client from the list
clients.removeElement(client);
// --- broadcast the new number of clients
broadcastMessage("<NUMCLIENTS>" + clients.size() + "</NUMCLIENTS>");
}
/**
* Writes a message to System.out.println in the format
* [mm/dd/yy hh:mm:ss] message.
* @param activity The message.
*/
public void writeActivity(String activity) {
// --- get the current date and time
Calendar cal = Calendar.getInstance();
activity = "[" + cal.get(Calendar.MONTH)
+ "/" + cal.get(Calendar.DAY_OF_MONTH)
+ "/" + cal.get(Calendar.YEAR)
+ " "
+ cal.get(Calendar.HOUR_OF_DAY)
+ ":" + cal.get(Calendar.MINUTE)
+ ":" + cal.get(Calendar.SECOND)
+ "] " + activity + "\n";
// --- display the activity
System.out.print(activity);
}
/**
* Stops the server.
*/
private void killServer() {
try {
// --- stop the server
server.close();
writeActivity("Server Stopped");
} catch (IOException ioe) {
writeActivity("Error while stopping Server");
}
}
public static void main(String args[]) {
// --- if correct number of arguments
if(args.length == 1) {
} else {
// otherwise give correct usage
System.out.println("Usage: java CommServer [port]");
}
CommServer myCS = new CommServer(3000);
}
}
//==================================================================
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// moock chat client
// version 1.0.1
//
// java server by derek clayton
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// *** general init
var incomingUpdated = false; // trace whether or not we need to scroll to the end of the incoming window
incoming = ""; // clear the HTML text field so it doesn't start with a blank <P> tag
// attach the scroll manager movie (see its child movie's enterframe event for scroll code)
// note that we only need the scroll manager because of text field bugs in r30 of the flash 5 player
attachMovie("processScroll", "processScroll", 0);
var click = new Sound(); // sound to play when user receives a message
click.attachSound("click");
var welcomeSound = new Sound(); // sound to play when user joins or leaves
welcomeSound.attachSound("welcome");
// turn off ugly yellow highlight on buttons
_focusrect = 0;
// *** creates a new socket and attempts to connect to the server
function connect () {
mySocket = new XMLSocket();
mySocket.onConnect = handleConnect;
mySocket.onClose = handleClose;
mySocket.onXML = handleIncoming;
// specify your server and port number here
if (!mySocket.connect("localhost", 3000)) gotoAndStop("connectionFailed");
mySocket.host = host;
mySocket.port = port;
}
// *** event handler to respond to the completion of a connection attempt
function handleConnect (succeeded) {
if(succeeded) {
mySocket.connected = true;
gotoAndStop("chat");
Selection.setFocus("_level0.outgoing");
} else {
gotoAndStop("connectionFailed");
trace("connection failed");
}
}
// *** event handler called when server kills the connection
function handleClose () {
incoming += ("the server at " + mySocket.host + " has terminated the connection.\n");
incomingUpdated = true;
mySocket.connected = false;
numClients = 0;
}
// *** event handler to receive and display incoming messages
function handleIncoming (messageObj) {
// display the received xml data in the output window
trace("--------new data received-----------");
trace(">>" + messageObj.toString() + "<<");
trace("-------- end of new data -----------");
// tell the text field manager it's time to scroll
incomingUpdated = true;
lastScrollPos = incoming.scroll;
// check the time
var now = new Date();
var hours = now.getHours();
var minutes = now.getMinutes();
var seconds = now.getSeconds();
hours = (hours < 10 ? "0" : "") + hours;
minutes = (minutes < 10 ? "0" : "") + minutes;
seconds = (seconds < 10 ? "0" : "") + seconds;
// the server sends NUMCLIENTS any time a client connects or disconnects.
// if we find NUMCLIENTS in the xml object...
if (messageObj.firstChild.nodeName == "NUMCLIENTS") {
// ...then check if the incoming messages window is empty. if it is...
if(incoming == "") {
// ...then the user is new, so welcome them
incoming += ("<FONT COLOR='#507373'><B>welcome to moock comm 1.0.1, "
+ convertTags(userID) + "\n"
+ " Connection time:</B> " + hours + ":" + minutes + ":" + seconds + "\n"
+ "<B> server:</B> 京华时报 Flash XmlSocket Chat Server</FONT>\n\n");
} else {
// otherwise, someone has arrived or departed, so tell the user
if(parseInt(messageObj.firstChild.firstChild.nodeValue) > numClients) {
// report the client arrival in the chat window
incoming += ("<FONT COLOR='#507373'><B>" + hours + ":" + minutes + ":"
+ seconds + " a new user has connected." + "</B></FONT>\n");
} else {
// report the client departure in the chat window
incoming += ("<FONT COLOR='#507373'><B>" + hours + ":" + minutes + ":"
+ seconds + " a user disconnected." + "</B></FONT>\n");
}
}
// finally, keep track of the number of clients and play a welcome sound
numClients = messageObj.firstChild.firstChild.nodeValue;
welcomeSound.setVolume(100);
welcomeSound.start();
} else {
// no NUMCLIENTS node was found, so this is just a regular message.
// grab the user name and message from our xml object
var user = messageObj.firstChild.firstChild.nodeValue;
var message = messageObj.childNodes[1].firstChild.nodeValue;
// add the message to the chat window, with a time stamp
incoming += (hours + ":" + minutes + ":"
+ seconds + "<B>" + unescape(user) + "</B>>> " + addLinks(unescape(message)) + "\n");
// now do the new message click. if it's been more than 30 secs since the last message,
// sound a loud click. otherwise sound a quiet click
trace("time since last message: " + (now - lastIncomingMessageTime));
if (lastIncomingMessageTime && now - lastIncomingMessageTime > 30000) {
click.setVolume(200);
} else {
click.setVolume(30);
}
click.start();
}
// truncate the contents of the incoming messages window if it's longer than 5000 characters
if(incoming.length > 5000) {
var nearestNewline = incoming.indexOf("\n", incoming.length - 5000);
incoming = incoming.substring(nearestNewline, incoming.length);
}
// remember when this message arrived for next time
lastIncomingMessageTime = now;
}
// *** sends a new xml object to the server
function sendMessage() {
// create the message to send as an xml source fragment. we're sending html so we
// have to escape our text and change < and > to entities via convertTags
var message = '<USER>%20' + escape(convertTags(userID)) + '</USER><MESSAGE>'
+ escape(convertTags(outgoing)) + '%20</MESSAGE>'; // note that the forced spaces (%20) are required so
// MESSAGE and USER always have a text child node
// convert the message into an xml object hierarchy
messageObj = new XML();
messageObj.parseXML(message);
// check what we're sending
trace("Sending: " + messageObj);
// if a socket object has been created and is connected, send the xml message
// otherwise warn the user that they need to connect
if (mySocket && mySocket.connected) {
mySocket.send(messageObj);
outgoing = "";
} else {
// the server must have kicked us off...
incoming += "<FONT COLOR='#507373'><B>you are no longer connected. please reconnect."
+ "</B></FONT>\n";
incomingUpdated = true;
}
}
// *** closes the connection to the server
function quit() {
if (mySocket.connected) {
mySocket.close();
mySocket.connected = false;
numClients = 0;
incoming = "";
gotoAndStop("login");
}
}
// *** changes < and > to < and >
function convertTags(theString) {
var tempString = "";
for(var i = 0; i < theString.length; i++) {
if(theString.charAt(i) == "<") {
tempString += "<";
} else if (theString.charAt(i) == ">") {
tempString += ">";
} else {
tempString += theString.charAt(i);
}
}
trace("tempString: " + tempString);
return tempString;
}
// *** inserts <A> tags into a string anywhere a "www" occurs
function addLinks (theString) {
var startIndex = 0;
var tempString = "";
var linkString;
var URL;
var beginURL;
var endURL;
if(theString.indexOf("www") != -1) {
while(theString.indexOf("www", startIndex) != -1) {
tempString += theString.substring(startIndex, theString.indexOf("www", startIndex));
beginURL = theString.indexOf("www", startIndex);
endURL = (theString.indexOf(" ", beginURL) != -1) ? theString.indexOf(" ", beginURL) : theString.length;
URL = theString.substring(beginURL, endURL);
linkString = "<A HREF='http://" + URL + "' TARGET='_blank'><U><FONT COLOR='#FFFFCC'>" + URL + "</FONT></U></A>";
tempString += linkString;
startIndex = endURL;
}
tempString += theString.substring(endURL, theString.length);
return tempString;
} else {
return theString;
}
}