5.17 Tutorial: External Zone Statistics

The example sources can be found under the Examples/AS2/zoneCount folder.

» Introduction

Since SmartFoxServer 1.5.0 we introduced a simple way to get the number of users logged in the server from an external client, like a PHP/ASP/JSP page or a SWF file. The operation is done by anonymously connecting to the server and sending a simple XML formatted request.

» How it works

The steps to get informations about one or more Zones are the following:

  1. enable the feature on the server by adding <EnableZoneInfo>true</EnableZoneInfo> in the main config.xml file.
  2. establish a socket connection to the server
  3. send the following XML:
    <msg t='sys'><body r='-1' action='zInfo'>zoneName</body></msg>
    where zoneName is the name of the zone that you want to inspect. You can also pass more multiple names, separating them with commas.

  4. close the connection

The server will respond with an XML message containing the number of users for each zone requested (comma separated).
Example:

<zInfo>255</zInfo>
or
<zInfo>255,100,20</zInfo>

In the first case you requested the user count for one Zone, the second case shows a response with the count for three Zones.

» PHP Sample script

The following code shows an implementation in PHP

<?php
	
	$port = 9339;
	$addr = "127.0.0.1";
	
	// Output basic HTML header
	echo "<html><head><title>SmartFoxServer Zone Count Demo</title></head><body style='font-size:70%; font-family:Arial'>";
	
	// Create a socket object
	$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
	if ($socket < 0)
	{
		trace("Socket errror: " . socket_strerror($socket));
		die();
	}
	else
		trace("Socket object created");
	
	// Establish connection
	$result = socket_connect($socket, $addr, $port);
	
	// Check connection
	if ($result < 0) 
	{
		trace ("Received: " . socket_strerror($result));
	} 
	else 
	{
		trace("Connection successfull");
		$handShake = "<msg t='sys'><body r='-1' action='zInfo'>simpleChat</body></msg>" . chr(0);
		socket_write($socket, $handShake, strlen($handShake));
		
		// Wait for server response
		while(true)
		{
			$out = socket_read($socket, 1024);
			trace("Received: " . htmlspecialchars ($out));
			
			if (strpos($out, "zInfo") > 0 )
			{
				$users = substr($out, 7);
				$users = substr($out, strpos($user, "<"));
				
				echo("<h2>Users in zone: $users<h2>");
				break;
			}
			
		}	
		
		// Close html tags
		echo "</body></html>";
		socket_close($socket);
	}

	function trace($msg)
	{
		echo "--> " . $msg . "<br/>";
	}

?>

In the first lines we start by creating a socket object and establish a connection to the provided address and port.
If the operation is successful we can send the XML request to the server and pass the zone name(s) that we need. The following while(true) loop waits for a server response that contains the expected zInfo token. Not necessarily the first response sent by the server is going to be what we expect: for instance if the auto-policy option is turned on the server will send the client the crossdomain policy data first, which is not what we need.

Once the zInfo tag is found we simply read its data (by skipping the token characters), output the result to the html page and finally break the while loop.

» Flash Sample script

If you want to display the number of users inside a SWF file you can directly connect to the server and retrieve the XML data using an XMLSocket connection.
The following is an example of how to do it:

 var request:String = '<msg t="sys"><body r="-1" action="zInfo">simpleChat</body></msg>'
var zeros:String = "000"

// Create a socket connection
var conn:XMLSocket = new XMLSocket()
conn.onConnect = connected
conn.onClose = closed
conn.onData = gotData

// Connect to SmartFoxServer
conn.connect("127.0.0.1", 9339)

// Handle connection to the server
function connected(ok:Boolean)
{
	// Connection successfull: send message to server
	if (ok)
	{
		trace("---> Connected")
		this.send(request)
	}
}

// Connection was closed
function closed():Void
{
	trace("---> Lost")
}


function gotData(msg:String)
{
	// Check if this is the message we're expecting
	if (msg.indexOf("zInfo") > -1)
	{
		var xml:XML = new XML(msg)
		var count:String = xml.firstChild.childNodes[0].toString()

		// Format the number
		userCount.text = zeros.substr(0, 3 - count.length) + count
		
		// Close connection
		conn.close()
	}
}

The socket connection is established using the XMLSocket object and it is handled by the onConnect() and onData() methods. The former checks if the connection was successful and sends the XML request, the latter handles the message received from the server and parses them.
When the zInfo token is detected we simply extract the data from the string and display it in the textfield on Stage called userCount.

If you're wondering why we didn't parse the XML data instead of manipulating the string, the reason is that the server response is so simple that it takes more code to do the XML parsing than just analyzing the plain string data.

» Using the embedded webserver (PRO only)

SmartFoxServer PRO 1.5.0 comes with a powerful embedded webserver that integrates with the SmartFoxServer framework.
If you're serving your application files from the embedded webserver it is very easy to show the current status of the server. An example of how to get the current server status is provided in the webserver/webapps/examples/ folder.

Open the ServerInfo.py file:

from javax.servlet.http import HttpServlet
from it.gotoandplay.smartfoxserver.webserver import WebHelper


class ServerInfo(HttpServlet):

	def __init__(self):
	  self.htmlHead = "<html><head></head><body style='font-family:Verdana'>"
	  self.closeHtml = "</body></html>"
	  
	  #
	  # Handle GET requests
	  #
	  def doGet(self, request, response): 
		w = response.getWriter()
		w.println(self.htmlHead)
	  
		status = WebHelper.getServerStatus()
		keys = status.keySet()
		
		w.println("<h2>SmartFoxServer :: Status</h2><hr>")
		w.println("<table cellpadding='6' cellspacing='0' border='0'>")
		w.println("<tr bgcolor='#eeeeee'><th align='left'>Key</th><th align='left'>Value</th></tr>")
		
		for key in keys:
		w.println("<tr>")
		w.println("<td>%s</td><td>%s</td>" % (key, status[key]))
		w.println("</tr>")
		
		w.println("</table><hr>")
		
		w.println(self.closeHtml)
		w.close()
	  
	  #
	  # Handle POST requests
	  #
	  def doPost(self, request, response): 
		pass

The doGet() handles a "regular" GET request to the webserver, which is what we expect in this case. (a POST request is handled when a form-data is sent to the page)

In order to access the SmartFoxServer status we have to first import the it.gotoandplay.smartfoxserver.webserver.WebHelper object.
The WebHelper class has a getServerStatus() method that returns a map (java.util.Map) of values with the following keys:

zones the number of active zones
rooms number of active rooms
users the number of active users
uptime the SmartFoxServer uptime
version current server version

In order to check the provided example you should open a browser page and point it to http://127.0.0.1:8080/examples/ServerInfo.py
(unless you have changed the default IP/port configuration parameters)

 


doc index