Servidor de chat

De SolarSockets C++ Sockets C++

Es un servidor de chat relativamente simple, pero que permite recibir múltiples conexiones, hacerlo a mano implica aun mas tiempo que el cliente, con SolarSockets y muy poco código obtendrás los mismos resultados. Ademas ya no tendrás que preocuparte por la capa de comunicaciones, nosotros lo hacemos por ti, en cambio puedes dedicar mas tiempo a la lógica de tu proyecto.

Para complicarlo un poco vamos a implementar 3 comando PING, QUIT e INFO. Ademas vamos a poner código para filtrar los cliente, por ejemplo si el cliente tiene IP 191.168.0.20 entonces rechazamos la conexión.

Nota: Para probar el servidor también se puede utilizar como cliente un cliente Telnet. Usado de la siguiente forma:

telnet localhost 9999

Descarga

serverChat.cpp

Copia y Pega

// Solar-OpenSource.Org (c)

#include <SolarSockets/SolarSockets.h>

bool EventoRecibe (string Cadena, int ID, ssServer* Server)
{

  /* ---- Inicia Modificacion para Telnet Windows ---- */
  // Telnet de Windows envia caracter por caracter cuando presionamos una 
  // tecla. 
  // pero un solo caracter no nos sirve de nada, por lo que tenemos que
  // concatenar los caracteres recibidos, uno por uno, y si nos llega un 
  // return, entonces ya tendremos una cadena completa.

  // Variable estatica, que servira para almacenar los datos hasta que 
  // llegue un "/r/n"

  static string Comandos = "";

  // Concatenamos
  Comandos = Comandos + Cadena;

  int fin;
  string CadenaCompleta;

  // Buscamos en return
  fin = Comandos.find("\r\n");
  // Si no lo encontramos no hacemos nada, en espera de que lleguen 
  // mas datos.
  if (fin == string::npos) return true;


  // Si encontramos un Fin de linea o return, cortamos hasta 
  // encontrar el return
  CadenaCompleta = Comandos.substr(0, fin+2);
  // Y el resto lo dejamos para la siguente.
  Comandos = Comandos.substr(fin+2, 999);

  // NOTA: Hay un error conceptual, dado que estamos usando la 
  // misma variable Comandos para todos los clientes conectados, y 
  // puede ocurrir que recibamos fragmentos enviados por clientes
  // diferentes. Lo ideal es que tengamos una variable Comandos
  // para cada Cliente, es decir una variable diferente para 
  // cada ID. Una forma de hacerlo es crear un array de variables 
  // Comando y usar una u otra para cada cliente.

  /* ---- Fin de la Modificacion para Telnet ---- */

  string Mensaje = "";


  if (CadenaCompleta == "PING\r\n") {

    // Contestamos con un Ping
    Server->Send ("PONG\r\n", ID);

  } else if (CadenaCompleta == "QUIT\r\n") {

    // Si nos envian la cadena QUIT lo desconectamos
    Server->Close (ID);

  } else if (CadenaCompleta == "INFO\r\n") {

    // Un cliente esta pidiendo informacion
    char CountChar[20]; // Convertimos de INT a CONST CHAR*</span>
    sprintf(CountChar,"%i",Server->Count());
    Mensaje = string("Numero de Clientes: ") + CountChar + "\r\n";
    Server->Send (Mensaje, ID);

  } else {

    // Convertimos de INT a CONST CHAR*
    char IDchar[20];
    sprintf(IDchar,"%i",ID);

    // Concatenamos todo para formar la respuesta
    Mensaje = Mensaje + "[Cliente:" + IDchar + " dice] " + 
              CadenaCompleta + "\r\n";
    cout << Mensaje;

    // Enviamos el mismo mensaje a todo los clientes, pero no al que lo envio.
    Server->SendMulticast(Mensaje, ID);
  }
  return true;
}

void EventoConectado (int ID, ssServer* Server)
{
  // Filtramos los cliente que queremos aceptar. 

  if (Server->getIP(ID) != "191.168.0.20")
  {
    // Aceptamos al nuevo cliente unicamente si su IP no es la 191.168.0.20
    Server->Accept();
    cout << "Cliente Conectado IP: " << Server->getIP(ID) << endl;
  }
  else
  {
    cout << "Cliente Rechazado IP: " << Server->getIP(ID) << endl;
  }
}

int main (void)
{
  // Declaramos un servidor
  ssServer ServerZeru;
 
  // Le decimod a que funcion hay que llamar cuando ocurra el evento Recive
  ServerZeru.setOnDataArrival(EventoRecibe);
 
  ServerZeru.setOnConnect(EventoConectado);

  // Lo ponemos a escuchar por el puerto 9999.
  ServerZeru.Listen(9999);

  cout << "Servidor escuchando por el puerto 9999" << endl;

  // Para que no se cierre inmediatamente.
  int X; cin >> X;
  return 0;
}



Español (es) English (en) +/-

Estadisticas
  • Modif 5 ene 2007.
  • Vista 3.017 veces.