Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | Related Pages | Examples

13. Pointer (complex: write - read - change)

In this test we do much the same as in the last test, except here we change what the objects are pointing at over time. When ever we change something we send updates to the clients.

Client Application

The client application is almost the same as in the last test. Except in this test we print out the PointerPointerTableThingy to make sure that this contains the expected values.

/// @cond EXCLUDEDTESTSOURCES
/***************************************************************************
 * The contents of this file are subject to the Mozilla Public             *
 * License Version 1.1 (the "License"); you may not use this file          *
 * except in compliance with the License. You may obtain a copy of         *
 * the License at http://www.mozilla.org/MPL/                              *
 *                                                                         *
 * Software distributed under the License is distributed on an "AS         *
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or              *
 * implied. See the License for the specific language governing            *
 * rights and limitations under the License.                               *
 *                                                                         *
 * The Original Code is Game Network Framework (GaNeF).                    *
 *                                                                         *
 * The Initial Developers of the Original Code are                         *
 * Lars Langer and Emanuel Greisen                                         *
 * Copyright (C) 2005. Lars Langer & Emanuel Greisen                       *
 * All Rights Reserved.                                                    *
 *                                                                         *
 * Contributor(s):                                                         *
 *   none yet....                                                          *
 *                                                                         *
 ***************************************************************************/

#include <iostream>
#include <cstdlib>

#include "../Ganef/client/clientframework.h"
#include "../Ganef/client/clientdata.h"


class MyClientData : public ClientData
{
   private:
      std::string name;
      MyClientData * child;

   public:
      MyClientData(ClientFramework * f, ClientPacket * p) : ClientData(f,p)
      {
         name = p->readString();
         p->readPtr(this, &child, f);
         std::cout << "Constructed a new object of class: MyClientData" << std::endl;
         std::cout << " - ID: " << getFrameworkId() << std::endl;
         std::cout << " - Name: "<<name<<std::endl;
         std::cout << " - Child: "<<(child ? child->name : "No child")<<std::endl;
      }
      virtual void updatePacket(ClientFramework * f, unsigned char updatetype, ClientPacket * p)
      {
         switch(updatetype)
         {
            case 42:
               p->readPtr(this, &child, f);
               std::cout << "Update of class: MyClientData" << std::endl;
               std::cout << " - ID: " << getFrameworkId() << std::endl;
               std::cout << " - Name: "<<name<<std::endl;
               std::cout << " - Child: "<<(child ? child->name : "No child")<<std::endl;
               break;
         }
      }

      static ClientData * constructMyClientData(ClientFramework * f, ClientPacket * p)
      {
         return new MyClientData(f,p);
      }
};


/**
 * This is just a test-client-framework.
 * @author Lars Langer and Emanuel Greisen
 */
class TestClientFramework : public ClientFramework
{
   private:
      bool is_running;
      std::string server_hostname;

   public:
      TestClientFramework(const std::string & server_hostname) : ClientFramework(int(0)),server_hostname(server_hostname)
      {
         // Notice how the constructor is registered, now all we need is the
         // server sending a packet telling us to construct an object of
         // class with id: 0x424242
         registerConstructor(0x424242, MyClientData::constructMyClientData);
      }
      ~TestClientFramework()
      {
      };

   protected: // These must be implemented in a derived class
      virtual void writeHandshakeInitMessage( ClientPacket * fp ){}
      virtual void onHandshakingDiscontinue( ClientPacket * fp ){}
      virtual bool onHandshakeDescription( ClientPacket * fp, ClientPacket * reply )
      {
         return true;
      }
      virtual void onDisconnect( ) { std::cout << "Disconnected\n"; }
      virtual void onConnect( ){ std::cout << "Connected\n"; }

   public:
      void mainLoop( )
      {
         std::cout << "Connecting to: " << server_hostname <<":"<< 8000<< std::endl;
         initServerConnection(server_hostname, 8000);
         is_running = true;
         int counter = 0;
         while(is_running)
         {
            // Get/handle Packets from the framework
            keepAlive();

            if(counter++ % 50 == 0)
            {
               printPointerPointerMapDebug( );
            }

            // Then we sleep to let the CPU live
            psleep(50);
         }
      }
};




int main(int argc, char *argv[])
{
   std::string server_host("localhost");
   if(argc > 1)
      server_host = argv[1];
   TestClientFramework app(server_host);

   // Start the Application
   app.mainLoop();
}

/// @endcond

Server Application

The server just flips the pointers around every now and then, and sends out updates about it.

/// @cond EXCLUDEDTESTSOURCES
/***************************************************************************
 * The contents of this file are subject to the Mozilla Public             *
 * License Version 1.1 (the "License"); you may not use this file          *
 * except in compliance with the License. You may obtain a copy of         *
 * the License at http://www.mozilla.org/MPL/                              *
 *                                                                         *
 * Software distributed under the License is distributed on an "AS         *
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or              *
 * implied. See the License for the specific language governing            *
 * rights and limitations under the License.                               *
 *                                                                         *
 * The Original Code is Game Network Framework (GaNeF).                    *
 *                                                                         *
 * The Initial Developers of the Original Code are                         *
 * Lars Langer and Emanuel Greisen                                         *
 * Copyright (C) 2005. Lars Langer & Emanuel Greisen                       *
 * All Rights Reserved.                                                    *
 *                                                                         *
 * Contributor(s):                                                         *
 *   none yet....                                                          *
 *                                                                         *
 ***************************************************************************/

#include <iostream>
#include <cstdlib>
#include <vector>


#include "../Ganef/server/serverframework.h"


class MyServerData : public ServerData
{
   public:
      std::string name;
      MyServerData * child;

   public:
      // The two last parameters for ServerData is the priority of its updatepackets
      //  and wether they should be sent reliable.
      MyServerData(ServerFramework * fw, const std::string & name, MyServerData * child) : ServerData(fw, 10, false),name(name),child(child)
      {
      };
   public:
      virtual const unsigned int getClassId() const { return 0x424242; };
      /// Here the data-class should fill in data according to update type `type`.
      virtual void fillUpdatePacket(ServerPacket * packet, unsigned char type) const
      {
         switch(type)
         {
            case 42:
               packet->writePtr(child);
               break;
         }
      }
      /// Here the data-class should fill in all data required by the constructor on the client side.
      virtual void fillCreateObjectPacket(ServerPacket * packet) const
      {
         packet->writeString(name);
         packet->writePtr(child);
      }
      /// Called when ever we receive a packet for this object from a client.
      virtual void clientPacket(Client * client, unsigned char type, ServerPacket * packet)
      {
         // We do not receive any actions from the client in this test.
      }
};

/**
 * This is just a test server-framework;
 * @author Lars Langer and Emanuel Greisen
 */
class TestServerFramework : public ServerFramework
{
   MyServerData * m_obj_a;
   MyServerData * m_obj_b;
   public:
      TestServerFramework() : ServerFramework(8000)
      {
      }

      ~TestServerFramework()
      {
      }

   protected: // These method should be implemented on the GameServer
      virtual bool onInitialHandshake(ServerPacket * handshake, ServerPacket * reply)
      {
         return true; // Accept all clients.
      }
      virtual void onClientConnected(Client * client)
      {
         std::cout << "Client: " << client->getId() << " connected\n";
         // Here we send the construction packages for the two objects,
         //  we send the pointee first to make sure it is constructed when the
         //  pointing object arrives.
         m_obj_a->sendCreateObject(client);
         m_obj_b->sendCreateObject(client);
      }
      virtual void onClientDisconnected(Client * client)
      {
         std::cout << "Client: " << client->getId() << " disconnected\n";
      }
      virtual Client * createClient(const ipaddress &addr, int port)
      {
         return new Client(this, addr, port);
      }

   public:
      void mainLoop()
      {
         std::cout << "TestServerFramework: Running\n";
         m_obj_a = new MyServerData(this, "The Pointee Objects", 0);
         m_obj_b = new MyServerData(this, "The Pointing Objects", m_obj_a);
         int counter = 0;
         while(true)
         {
            // Get all incomming messages
            keepAlive();

            if(getAllClients().size() > 0)
            {
               counter++;
               if(counter == 100)
               {
                  std::cout << "Change objects\n";
                  m_obj_a->child = m_obj_b;
                  m_obj_b->child = m_obj_b;
                  m_obj_a->sendUpdateToAll(42, true);
                  m_obj_b->sendUpdateToAll(42, true);
               }
               else if(counter == 200)
               {
                  std::cout << "Change objects\n";
                  m_obj_a->child = 0;
                  m_obj_b->child = m_obj_a;
                  m_obj_a->sendUpdateToAll(42, true);
                  m_obj_b->sendUpdateToAll(42, true);
               }
            }

            // Sleep a little
            psleep(100);
         }
      }
};




int main(int argc, char *argv[])
{
   try
   {
      // Create a framework
      TestServerFramework framework;

      // Start the framework
      framework.start();

      // GameLoop
      framework.mainLoop();
   }
   catch(FrameworkError *err)
   {
      std::cout << "FrameworkError:" << err->msg << std::endl;
   }
   catch(PacketError *err)
   {
      std::cout << "PacketError:" << err->msg << std::endl;
   }

   return EXIT_SUCCESS;
}

/// @endcond

Generated on Mon Feb 6 12:24:58 2006 for Ganef by  doxygen 1.4.4