Example10_NetChat.cpp

logotipo.png


/*
  How to use CRM32Pro SDK. Example 10: using INetwork on Non-Authoritative mode
  -----------------------------------------------------------------------------

  >MegaStorm Systems (c) 2007
  >http://www.megastormsystems.com
  >Roberto Prieto
  
  - Initialize CRM32Pro and SDL.
  - Printing help on console.
  - Use of log system.
  - Initializing network system.
  - Using Non-Authoritative Server Mode.
  - Each instance run as server or as client.
  - Simple chat.
  - Exiting using right way ;)
  
 */

// ---Includes---
#include "CRM32Pro.h" 

// ---Defines---
#define EXAMPLE_VERSION "Example 10: INetwork on Non-Authoritative mode"

// ---Prototypes---
void ExecuteClient(char *server,char *myname);
void ExecuteServer();
int ReadLine(void *);
void PrintHelp(char *sErrMsg = NULL);

// ---Global vars---
int done; // Used by "ReadLine()" thread to finalize

// -------------MAIN FUNCTION----------------
int main(int argc,char **argv)
{       
   Uint8       bMode = 0;

   // -Print help without any arguments-
   if(argc < 2) 
   {
           PrintHelp();
           return 1;
   }

   // -Get arguments from command line-
   if(!strcmp(argv[1],"-s")) 
   {
           // Run as server
           bMode = 1;  
           // Log system initialize
           ILogSystem.Init("NetChatServer.log",LOG_CONSOLE | LOG_FILE,LOG_NORMAL,EXAMPLE_VERSION);
   }
   else if(!strcmp(argv[1],"-c"))
   {
          if(argc > 2) 
          {
                  // Run as client
                  bMode = 2; 
                  // Log system initialize
                  ILogSystem.Init("NetChatClient.log",LOG_CONSOLE | LOG_FILE,LOG_NORMAL,EXAMPLE_VERSION);
          }
   }

   // -Are the arguments OK?-
   if(bMode == 0) 
   {
           PrintHelp("\n Error: invalid arguments\n");
           return 1;
   }
   
   // -CRM32Pro and SDL initialize- 
   if(CRM32Pro.Init(0) < 0)
   {
      ILogSystem.Msg(LOG_NORMAL," · [LOG] - Could not initialize CRM32Pro: %s\n",SDL_GetError());
      return 1;
   }

   // -Interfaz network initialize-     
   if(!INetwork->Init(LOG_CONSOLE | LOG_FILE))
   {
      ILogSystem.Msg(LOG_NORMAL," · [LOG] - Could not initialize INetworkSystem\n");
      CRM32Pro.Quit();
          return 1;
   }

   // -Execute a server or a client-
   if(bMode == 1) ExecuteServer();
   else 
   {
           // Look for a client name
       if(argc > 3) ExecuteClient(argv[2],argv[3]);
           // Or use a default one
           else ExecuteClient(argv[2],"Anonymous");
   }

   // -Exiting..-   
   INetwork->Quit();
   CRM32Pro.Quit();
   return 0;
}

// -------------------CLIENT STUFF-----------------------
// -Execution of a client-
void ExecuteClient(char *server,char *myname)
{
   char       *buff = NULL; 
   Uint32 size = 0, result = 0;
   SDL_Thread *ReadLineT = NULL;

   // -Trying to connect to server on port 2200 with password 1001-
   if(!INetwork->ConnectTo(server,2200,myname,1001)) return;
        
   // -Using a thread, we can send/receive data at the same "time"-
   // We have a little chat ;)
   ReadLineT = SDL_CreateThread(ReadLine,NULL);         

   // -Main Loop-
   done = 0;
   
   while(!done)
   {    
      // Have we received data?
      result = INetwork->ReceiveData(&buff,&size);              
      switch(result)
      {
        case INETWORK_ERROR:
                        puts("Error detected!");
         case INETWORK_CLOSE:
                        puts("Closing application. Press ENTER to finish");
                        // With done = 1, the reading thread should finish by itself
                        done = 1; 
                        // Waiting for the end of our reading thread                    
                        SDL_WaitThread(ReadLineT,NULL);
                        ReadLineT = NULL;
                        break;
         case INETWORK_NEWCLIENT:
                        ILogSystem.Msg(LOG_NORMAL,"[New client '%s' connected]\n",buff);
            break;
         case INETWORK_QUITCLIENT:
                        ILogSystem.Msg(LOG_NORMAL,"['%s' client has quitted]\n",buff);
            break;
         case INETWORK_PING:
            break;
                 case INETWORK_CLIENTSINFO:
                        ILogSystem.Msg(LOG_NORMAL,"[Clients information updated]\n");
            break;
         case INETWORK_DATA:
            ILogSystem.Msg(LOG_NORMAL,":%s(%dbytes)\n",buff,size); 
                        break;
      }
      // Delete received data (if any)
      INetwork->FreeData(buff);
      // Your code...we only wait 250ms
      SDL_Delay(250);
   }
   // It's not necessary to kill our thread because it finishes by itself with done=1
}

// -Our thread to read a line and send it-
#define MAXLEN (1*1024) // 1 KB - adequate for text!
int ReadLine(void *data)
{       
   char     message[MAXLEN];
   Uint32   len = 0, nc,i;
   char    *str;
   sClientInfo *cInfo;
   strcpy(message,"");

   // ---Main loop---
   while(!done)
   {
      strcpy(message,"");       
          // As we are not using a non blocking read method, quite probably we will have to press ENTER
          // to finish this thread, but the user will be informed on that case  
      fgets(message,1024,stdin);
      len = (int)strlen(message);      
      SDL_Delay(250);
      if((len) && (!done))
      {
                 message[len - 1] = '\0';

         // -With '1', query to close this client-
         if(message[0] == '1') INetwork->QueryKillClient();
                        
         // -With '2', query to close the server (and all clients)
         else if(message[0] == '2') INetwork->QueryKillServer();

         // -With '3', query a list of current clients with updated information
         else if(message[0] == '3') INetwork->QueryClientsInfo();
                        
         // -With '4', send raw data to server-
         #define HOW_KB 32*1024
         else if(message[0] == '4')
         {
            len = HOW_KB;
            str = new char[len];        
                        memset(str,0,len);
            ILogSystem.Msg(LOG_NORMAL,"[Sending a block of %dKb raw data]\n",len / 1024);                                                                       
            INetwork->SendData(str,len);
            delete str;                                 
         }

                 // -With '5', show our local clients information table-
                 else if(message[0] == '5')
                 {
                         nc = INetwork->GetClientsInfo(&cInfo);
                         ILogSystem.Msg(LOG_NORMAL," Number of clients: %d\n",nc);
                         for(i = 0; i < nc; i++)
                         {
                                 ILogSystem.Msg(LOG_NORMAL,"Client '%s' - IP '%d.%d.%d.%d' - Current %dms - Average %dms.\n",
                                         cInfo[i].szName,cInfo[i].IP >> 24,(cInfo[i].IP >> 16) & 0xff, (cInfo[i].IP >> 8) & 0xff,
                                         cInfo[i].IP & 0xff, cInfo[i].iLatency, cInfo[i].iLatencyAvg);
                         }

                 }

                 // -With '6', show current statistic-
                 else if(message[0] == '6')
                 {
                         INetwork->Info();
                 }
                                        
         // -Send a text line-
         else
         {                              
            ILogSystem.Msg(LOG_NORMAL,"[Sending a text line of %d bytes]\n",len);                                                                       
            INetwork->SendData(message,len);
         }
      } 
   }
   return 1;
}


// -------------------Server STUFF-----------------------
// -Execution of a server-
void ExecuteServer()
{
   // Create a dedicatedserver listening on port 2200 and with 1001 as password
   if(!INetwork->CreateServer(2200,1001,1)) return;
}

// --------------------Help STUFF------------------------
// -Print help-
void PrintHelp(char *sErrMsg)
{
        printf("-----------------------------------------------------------\n");
        printf("                 CRM32Pro SDK - HelpScreen\n    %s\n",EXAMPLE_VERSION);
    printf("-----------------------------------------------------------\n\n");
        printf(" Use:\n");
        printf("   -  'NetChat -s' to run as server\n");
        printf("   -  'NetChat -c ServerIP [my_name]' to connect to a server\n\n");
        printf(" Once you are connected to a server, you can press [ENTER]\n");
        printf(" key to send any text to others clients.\n");
        printf(" There are a few words that are reserved internally:\n");
        printf("  > '1' the client wants to exit\n");
        printf("  > '2' the client wants to close the server\n");
        printf("  > '3' the client has asked for info about clients(including itself)\n");
        printf("  > '4' the client sends a raw block data of %dKB\n",HOW_KB/1024);
        printf("  > '5' the client dumps the local clients information\n");
        printf("  > '6' the client shows the current statistics\n");
        if(sErrMsg != NULL) printf("%s",sErrMsg);
        else printf("\n");
        puts("Press [ENTER] key to continue");
        getchar();
}

Generated on Mon Dec 21 17:04:39 2009 for CRM32Pro SDK v5.00 by  doxygen 1.6.1