overview

study the basic principles of multiuser application development

look at some of the code required to create a multiuser flash application

explore Unity, a multiuser application development kit

what is a multiuser application?

multiuser app: many users simultaneously experiencing the same environment

for example, a chat or a shared whiteboard (see simpledraw)

users connect to central server application

the server application manages:

  • the shared environment
  • communication between users
  • application that connects to server is a "client application" (aka a "client")

    multiuser application requirements

    fast communication between client and server (high responsiveness)

  • speed guarantees that all users experience the same environment
  • a persistent connection between the client and the server

  • connection persistence allows the server to update clientA when clientB sends a message
  • tcp/ip socket connections in flash

    flash supports two systems for creating multiuser apps

  • flash communication server (RTMP)
  • XMLSocket (transfer XML over tcp/ip)
  • Unity is an XMLSocket server

    both flashcom and xmlsocket clients connect to the server over persistent tcp/ip connections

    XMLSocket-based applications

    to create an XMLSocket based application, we must:

    1) create a server application that...

  • manages client connections
  • interprets messages from clients
  • sends messages to clients, typically in XML format but can be any format
  • 2) create a client application that...

  • creates an instance of XMLSocket
  • connects to server via the XMLSocket instance (XMLSocket.connect())
  • sends and receives messages using XMLSocket.send() and XMLSocket.onData() or XMLSocket.onXML()
  • XMLSocket client basic code

    here's the basic code required to make an XMLSocket-based client

    create an XMLSocket instance

    var xsock:XMLSocket = new XMLSocket();

    define a method to handle incoming messages

    xsock.onXML = function (xmlObj:XML):Void { trace("Some XML arrived:"); trace(xmlObj); };

    define a method to handle connection information

    xsock.onConnect = function (success:Boolean):Void { if (success) { // We're connected! trace("Connected to server."); // Now we can send a message to the server. // We're using Unity 2 in this test, so we'll send // an arbitrary message that Unity understands. this.send("<UPC><ROOMID>unity</ROOMID><METH>getNamespaceList</METH></UPC>"); } else { trace("Connection to server failed.") } };

    attempt to connect our XMLSocket instance to the server

    var connectSuccess:Boolean = xsock.connect("localhost", 9100); if (connectSuccess) { trace("Initial connection attempt succeeded. Waiting for response from server."); } else { trace("Initial connection attempt failed"); }

    the need for a framework

    challenge of creating multiuser apps is not using XMLSocket

    challenge is managing communication and logic between potentially hundreds of clients

    every multiuser app, whether business, art, or games, needs the same basic features:

  • notification when a user joins/leaves
  • send messages to other clients (i.e., invoke remote methods)
  • receive messages from other clients
  • check state of other clients (i.e., retrieve data)
  • check state of shared environment (chat room name, location of chess pieces in a game of chess)
  • manage clients in groups (2-player game, multiple chat rooms, etc)
  • rather than recreate those features from scratch for each project, it's better to use a framework, such as Unity

    Unity overview

    Unity is a generic framework for developing multiuser applications

    can use it to make any kind of multiuser application (not just chat)

    Unity Multiuser Development Kit has two parts:

  • Unity Multiuser Server
  • UClient for Macromedia Flash
  • Unity Multiuser Server

    Java-based

    handles client connection/disconnection

    manages client communications

    manages client groups

    handles database connectivity

    supports multiple client types (Java, C++, Flash, etc)

    no audio/video support

    UClient for Macromedia Flash

    ActionScript 2.0 class library for application development

    extensive collection of samples and templates

    allows client-only development: Unity apps can be created entirely in flash. no server code required.

    Unity core concepts

    fundamental architecture: "groups of connected users that communicate by sharing data and invoking methods on each other"

    clients

  • user connected to the server
  • rooms

  • groups of clients
  • namespaces

  • groups of rooms
  • room attributes

  • shareable data pertaining to rooms
  • client attributes

  • shareable data pertaining to clients
  • remote method invocation

  • invoke methods on any user, or on the server
  • the server, illustrated

    clients

    users connected to the server

    can be anonymous or registered (i.e., required to log in)

    whether registered or not, every client gets a server-generated id

    represented by two actionscript classes:

  • UClient
  • RemoteClient
  • UClient class

    UClient makes the initial connection to the server

    handles all communication with the server

    used to register and login clients

    provides central access to room list and other clients on the server

    used to set client attributes

    used to invoke methods on other clients

    RemoteClient class

    RemoteClient represents other users connected to the server

    stores information about the user:

  • IP address
  • connection time
  • ping
  • list of rooms the user is in
  • client attributes
  • client attributes

    client attributes are like variables for each client

    when a client sets an attribute, other clients see the new value automatically

    client attributes are managed by the server

    client attributes can be saved permamently to a database

    example uses:

  • user name in a chat application
  • user's drawing pen color in a whiteboard application
  • the contents of a user's shopping cart
  • the user's position in a game
  • a user's inventory in a game
  • client attribute code example

    a client sets an attribute with setClientAttribute()

    others respond to the change with onUpdateClientAttribute()

    for example, here's the code to set the client attribute "username":

    client.setClientAttribute("username", "dave", null, true, false, false, true);

    parameters are: attribute name, attribute value, scope, attribute is shared, attribute is persistent, value is appended, attribute value is unique

    code to respond to a change in the client attribute "username":

    public function onUpdateClientAttribute (e:URoomEvent):Void { var attrName:String = e.getChangedAttr().attrName; var attrVal:String = e.getChangedAttr().attrVal; var oldVal:String = e.getChangedAttr().oldVal; var clientID:String = e.getClientID(); var status:String = e.getStatus(); // If the username changed display the new info on screen. if (attrName == "username") { handleUsernameUpdate(clientID, attrVal, status); } }

    remote method invocation

    use UClient class to invoke methods on other clients

    invoke methods on an individual user or groups of clients

    four remote-invocation methods:

  • UClient.invokeOnClient()
  • UClient.invokeOnRoom()
  • UClient.invokeOnNamespace()
  • UClient.invokeOnAll()
  • remote method invocation example

    this code invokes displayMessage() on all clients in the room "chatapp.sportsChatRoom":

    theUClient.invokeOnRoom("displayMessage", "chatapp.sportsChatRoom", true, "Hello world!");

    "chatapp" is the namespace

    third argument, true, indicates that the method should also be invoked on the message sender

    fourth argument, "Hello world!", is passed to displayMessage()

    other clients in the room must implement displayMessage() method

    public function displayMessage (clientID:String, msg:String):Void { output.text += "User" + clientID + " says: " + msg + "\n"; }

    rooms

    room is a group of users

    in actionscript, rooms are represented by the URoom class

    URoom instances are created automatically when a room is added to the server

    URoom instances broadcast the following events:

  • onAddClient()
  • onRemoveClient()
  • onJoin()
  • onLeave()
  • onNumClients()
  • onUpdateRoomAttribute()
  • onUpdateClientAttribute()
  • creating rooms

    rooms can be created in three ways:

  • using a configuration file on the server
  • using the server-side RoomManagementServices class (java)
  • using the client-side RoomManager class (actionscript)
  • for example, this ActionScript code creates a new room:
  • getRoomManager().createRoomOnServer("sportsChatRoom", "chatapp", true, true, 50);

    arguments: room name, containing namespace, dieOnEmpty, clientListNotification

    when a room is created, the namespace containing it broadcasts an onAddRoom() event

    joining and leaving rooms

    to join a room, use URoom.join()

    theClient.getRoomManager().getRoom("chatapp.sportsChatRoom").join();

    to leave a room, use URoom.leave()

    theClient.getRoomManager().getRoom("chatapp.sportsChatRoom").leave();

    room attributes

    room attributes store information about the environment

    for example:

  • the high score of a game room
  • the position of furniture in a 3d world
  • this code sets a "highscore" attriubte

    theRoom.setAttributeOnServer("highscore", "1000", true, true, false);

    arguments are: attr name, attr val, isShared, isPersistent, appendVal

    clients respond to a change in a room attribute using onUpdateRoomAttribute():

    public function onUpdateClientAttribute (e:URoomEvent):Void { if (e.getChangedAttr().attrName == "highscore") { highscore_txt.text = e.getChangedAttr().attrVal; } }

    namespaces

    namespace is a group of rooms

    create namespaces to hold rooms

    in actionscript, namespaces are represented by the NameSpace class

    use RoomManager.createNamespaceOnServer() to create namespaces

    NameSpace instances broadcast the following events:

  • onAddRoom()
  • onRemoveRoom()
  • onNumClientsInNamespace()
  • onDie()
  • an example: chat

    let's look an example: a chat application

    basic characteristics of a chat:

  • users can send messages to each other (remote method invocation)
  • users can set their name (client attriubtes)
  • users communicate in groups (rooms)
  • logic flow: creating and joining a room

    here's the logic flow for creating and joining a room in a simple chat app

    logic flow: setting a user name

    here's the logic flow for setting a user name in a simple chat app

    logic flow: sending a chat message

    here's the logic flow for sending a message in a simple chat app

    uClientCore architecture

    here's the basic architecture for an application built with uClientCore:

    example chat architecture

    here's the basic architecture for a chat application:

    questions?

    any questions? email unity@moock.org