Encontrar salas de chat con C#

Iniciado por TickTack, 4 Julio 2017, 16:04 PM

0 Miembros y 2 Visitantes están viendo este tema.

TickTack

Hola ivancea96,

Citar
Si el servidor tiene una lista de salas que va acumulando cada vez que un cliente le dice de crear una sala

Pero el cliente no le va decir al servidor eso. Es mas: cómo se lo va decir si todavia no sabe que existe esa sala?


Gracias y saludos
Citar
"Ninguna mentira puede inventarse lo suficientemente patán: el pueblo hispanohablante la cree. Por una consigna que se les dio, persiguieron a sus compatriotas con mayor encarnizamiento que a sus verdaderos enemigos."

Serapis

Como os gusta complicaros la vida...

Vamos a ver, quién crea la sala?.
en teoría debería crearla el servidor, de entrada debería crear varias salas por defecto, y luego permitir a los usuarios crear otras salas. Por tanto el cliente que quiera crear una sala, debería hacer una petición al servidor, pasándole los parámetros de la sala... nombre delcreador, nombre d ela sala, máximos clientes en la sala, tipo de permisos o privilegios, si es visible a todos o solo admite clientes por invitación, etc, etc, etc... (lo que se te ocurra que queiras que haga tu chat).
Con esa petición, el servidor comprueba dichos parámetros (que sean válidos y dentro delrango permitido) y que no exista ya una sala con ese nombre o que no se haya alcanzado el límite máximo de salas... y en respuesta devuelve al cliente si la sala fue creada o no, y si fue creada, el canal... además actualiza la lista de salas, que entrega a todos los clientes en cuanto pueda...

Pero básicamente si tu estás creando un chat, son cosas que decides tú, quién cuándo y cómo se hace qué... pués eres tú quien lo diseña.

ivancea96

Cita de: TickTack en  5 Julio 2017, 11:43 AM
Hola ivancea96,

Pero el cliente no le va decir al servidor eso. Es mas: cómo se lo va decir si todavia no sabe que existe esa sala?


Gracias y saludos

Para crear una sala, no tiene que  existir. No puede existir. Crearla implica que aparezca una sala donde antes no la había.

En caso de que se quiera unir, sí, el cliente sí que sabe qué salas existen, porque se lo puede preguntar al servidor. El servidor sí sabe qué salas existen (por ejemplo, en IRC). El servidor tiene la información, el cleinte también, pues el servidor se la provee. Entonces, ¿qué problema hay?

TickTack

Hola NEBIRE,

Citar
en teoría debería crearla el servidor, de entrada debería crear varias salas por defecto

Un servidor que crea salas? Y si uno quiere una sala nada mas?
Tomemos como ejemplo Sb0t y Ares para no confundirnos mas:
Sb0t deberia crear varias salas por defecto? Que yo sepa, Sb0t no hace eso.

Citar
Por tanto el cliente que quiera crear una sala

Ares, el lado del cliente no crea salas. Sino no seria cliente, sino servidor.

Gracias y saludos

Hola ivancea96,

tomemos como ejemplo Sb0t y Ares para no confundirnos mas:

Citar
En caso de que se quiera unir, sí, el cliente sí que sabe qué salas existen, porque se lo puede preguntar al servidor.

A que servidor? A cualquiera? Como va a hacerle Ares eso a Sb0t en un principio si todavia no tiene ni ip ni puerto de ninguna sala?

Gracias y saludos
Citar
"Ninguna mentira puede inventarse lo suficientemente patán: el pueblo hispanohablante la cree. Por una consigna que se les dio, persiguieron a sus compatriotas con mayor encarnizamiento que a sus verdaderos enemigos."

ivancea96

Ares se conecta a un servidor. Uno por defecto suyo o uno que le das tú, no lo sé, no lo utilizo, pero se conecta.

Las "salas" son algo interno de las aplicaciones. Lo único que tiene que quedar claro, es que hasta un cliente P2P que te muestra "cosas para descargar" o "salas" o lo que quieras, se ha conectado a un servidor o el cliente le ha añadido esa información manualmente o traía esa información ya en el propio cliente.

Dado por concluído el tema de que hay un servidor que te da la información, como en Ares, como en IRC, como en eMule... El tema de obtener las salas (aka "cualquier información") es algo que se consigue pidiéndoselas al servidor.

TickTack

Hola ivancea96,

Citar
Lo único que tiene que quedar claro, es que hasta un cliente P2P que te muestra "cosas para descargar" o "salas" o lo que quieras, se ha conectado a un servidor

Osea que alguien tiene la computadora las 24hs abierta para recibir salas y enviar informacion de salas abiertas del Ares?

Citar
o el cliente le ha añadido esa información manualmente

De que manera?

Citar
o traía esa información ya en el propio cliente

Imposible ya que al abrir una sala se actualiza la lista de salas sin tener que liberar una nueva version del cliente.

Gracias y saludos
Citar
"Ninguna mentira puede inventarse lo suficientemente patán: el pueblo hispanohablante la cree. Por una consigna que se les dio, persiguieron a sus compatriotas con mayor encarnizamiento que a sus verdaderos enemigos."

ivancea96

Cita de: TickTack en  5 Julio 2017, 19:06 PM
Osea que alguien tiene la computadora las 24hs abierta para recibir salas y enviar informacion de salas abiertas del Ares?

Eso es el servidor. Sí, está 24 horas abierto. Y no, no es una computadora si nmás. Es el servidor de Ares al que te conectas. Cuando la gente dice que se ha caído, es porque no está abierto.
Que sea P2P no implica que no haya servidor. Sin un primer nodo al que conectarse, ninguna red se puede formar.

Serapis

Cita de: TickTack en  5 Julio 2017, 17:22 PM
Un servidor que crea salas? Y si uno quiere una sala nada mas?
Qué funciones crees tú que tiene el servidor????.
Colectar clientes y salas. Los clientes existen, no se crean pero al caso los loguea/conecta (que es conceptualmente lo mismo), ...pero
...y las salas?... no son entes propios o sí?... qué crees tú que son las salas?.
No existen en ninguna parte. Las crea (virtualmente) el servidor a petición de un cliente (si el diseño del servidor permite que cualquier cliente pueda crearlas (o solo clientes con determinados privilegios (los llamados administradores)).

Una sala al fin y al cabo, no es más que un selección de clientes... una colección de clientes, con unas simples propiedades... desde el punto de vista programático, es así de sencillo, instancias de una colección específica, que reúne clientes y comparten eventos a los que todos los clientes que tienen una referencia de esa instancia, están suscritos, y entre sus propiedades puede estar por ejemplo el nombre de la sala... NumeroMaximoUsuarios, cantidadUsuarios, o métodos como AliasDelPropietario, CambiarPrivilegiosDeCliente, ExisteCliente, Addcliente, RemoveCliente, etc...

Cita de: TickTack en  5 Julio 2017, 17:22 PM
Tomemos como ejemplo Sb0t y Ares para no confundirnos mas:
Sb0t deberia crear varias salas por defecto? Que yo sepa, Sb0t no hace eso.
Desconozco, lo que haga tal o cual programa. La pregunta no debe ser qué hace tal programa, la pregunta debe  ser qué quieres hacer tú... Si lo que quieres es copiar a otros programas, entonces hazte con una copia del código y estudialo a fondo. Si lo que quieres es diseñar tu propio chat bajo tus propios criterios, pués adelante...

Cita de: TickTack en  5 Julio 2017, 17:22 PM
Ares, el lado del cliente no crea salas. Sino no seria cliente, sino servidor.
Insisto... ¿qué quieres hacer?. copiar lo que hace otro programa?... si es que sí busca su código... de todas maneras, las cosas tiene diferentes maneras de resolverse y pensar en copiar lo que hace un programa por que sí, es algo patético. Yo jamás hago algo basado en el hecho de que 'es lo que hacen los demás', como programador, cuando hago algo, lo hago convencido de que es lo mejor que s epuede hacer (dados los recursos de que se dispongan (como el tiempo))... conformarse con copiar, es aspirar... a nada, una copia jamás mejora un original, entonces por qué nadie va a usar una copia teniendo disponible el original, si la copia es mucho peor...

Si quieres crear un chat, no tienes por qué copiar todos y cada uno d elos detalles que tengan otros, lo razonable es que tú tengas ideas propias que puedna aportar soluciones o novedades que incluyan mejoras o diferencias significativas que se ditingan del resto... hacer un clónico solo por hacerlo, suele ser una pérdida de tiempo... y casi siempre es mucho más ineficiente.

----
en fin yo te digo como lo plantearía:

Si tienes la lista de usuarios-clientes conectados global, esa lista es privada. Puede haber una petición para que un cliente obtenga la lista de salas, mejor si cuando se conecta, se la entrega, también un actualización cuando se crea una nueva sala.

Crearía una función para que un cliente (o solo aquellos con determinados privilegios), puedan crear salas, con un evento para actualizar la lista de salas a todos losclientes (quizás determinadas salas solo estén disponibles para los administradores, o bien que requiera supervisión de un administrador, la 'publicación' de una nueva sala. Y una función para que un usuario se mueva de una sala a otra.

La sala como te he dicho, no es más que una instancia de una colección, que almacena básicamente clientes. Y que entre ellos se interconectan porque comparten la misma referencia a dicha instancia. Todo controlado por eventos...

Pero tú mismo, si quieres imitar a otros programas, lo mejor es que te hagas con el código de alguno...

Serapis

#18
---------------------------- NUEVO MENSAJE ------------------

Como pareces duro de mollera  :silbar: :silbar: :silbar: un poco de pseudocódigo que te ayude a clarificar ideas... que no es todo tan abstracto...

Te pongo un simple ejemplo de lo que sería un servidor, un cliente y una sala...

El pseudocódigo de un servidor....
Clase Servidor
  // Instancias de clases.
  TablaHash Clientes Privado ConEventos
  TablaHash ClientesOcultos Privado  ConEventos // clientes privilegiados, admins
  TablaHash Salas Privado ConEventos
  Sala SalaRaiz  Privado ConEventos
  Cliente ClienteRaiz  Privado ConEventos

  Buleano Existe

  Entero = Propiedad Sololectura NumClientes Publico
      Numclientes = Clientes.Cantidad
  Fin Propiedad

  Entero = Propiedad SoloLectura NumclientesOcultos Publico // o admins  
      NumClientesOcultos = ClientesOcultos.Cantidad
  Fin Propiedad
 
  Entero = Propiedad SoloLectura NumSalas Publico
      Numsalas = Salas.Cantidad
  Fin Propiedad

  Buleano = Propiedad SePermiteCrearSalas Oculto //lectura y escritura

 
  // Esta función se invoca para crear el servidor, que luego es público y permite la conexión... crea además, la primera sala y el resto de objetos necesarios.
  Funcion Nuevo(x,y,z) Oculta  ' parámetros que requiriese para crear el servidor
      Clientes = Nueva TablaHash
      ClientesOcultos = Nueva TablaHash
      Salas = NuevaTablaHash

      SalaRaiz= Nueva Sala
      ClienteRaiz = Nuevo Cliente(Alias, Invisible, Privilegios)
     
      Salas.Add(SalaRaiz)
      Clientes.Add(ClienteRaiz)
      ClientesOcultos.Add(ClienteRaiz)

      Existe = TRUE
   Fin Funcion
   
   // El ciente cuando se conecta al servidor, se añade a la lista de clientes.
   // Y también se le añade a la salaRaiz, y se le devuelve una referencia a esa sala.
   Sala = Funcion Conectar(Cliente Cli) Publico
       Si SalaRaiz.AdmiteClientes = TRUE luego
          //podría filtrarse aquí comparando con una lista de clientes/IPs, baneadas, pero quizás no sea muy efectiva...
            Si SalaRaiz.Add(cli) = TRUE  // solo debería devolver false si ya existe un cliente con el mismo alias.
                Devolver SalaRaiz
            Fin si
       Fin si
   Fin Funcion        

   Sala = Funcion CrearSala(Cliente Cli, String NombreSala, Entero MasUsers)
       Si (SePermiteCrearSalas = TRUE) luego
           Si (Clientes.Existe(cli) = TRUE ) luego  // Todos los clientes, incluso los ocultos, constan en la colección Clientes.
               Si (Salas.Existe(NombreSala) = FALSE) luego
                   Sala = Nueva Sala(Cli, Nombresala, MaxUsers, This)
                    Salas.Add(sala)  //allí se dispara un evento de 'SalaCreada(Sala.nombre)' que le llega a todos los clientes.

                   Devolver Sala
               Fin Si
           Fin si
       Fin si


       // Ó si solo se permite a clientes ocultos (admins).
       Si (ClientesOcultos.Existe(cli) = TRUE ) luego ...
       ....

       // Ó si solo se permite a cliente con privilegios
       Si (cli.Privilegios.Contiene("CreateSala")) luego
           Si (Clientes.Existe(cli) = TRUE ) luego ...
           ....
       Fin si
   Fin Funcion

   // Otras funciones que tenga el servidor... (especialmente resolver los eventos de las intancias de las clases: Clientes, ClientesOcultos, Salas,  SalaRaiz, ClienteRaiz
Fin Clase


En alguna web (por ejemplo), cuando quien sea prende la máquina, ejecuta un programa que crea una instancia única del servidor.

Servidor WebServer = nuevo Servidor(x,y,z)
Y lo pone a la escucha, ahora cuando algún cliente ejecute su programa, ya en su programa reconoce la clase de tipo Servidor, y por tanto espera conectarse y obtener un referencia a la instancia... dejando aparte los detalles de la conexión (que se supone que es algo que dominas), y centrándonos en lo que importa, el cliente hac ela llamada.

Servidor ServerCliente = Lllamada(www... puerto... cliente...)
Si obtienes la referencia dle servidor, el programa cliente típicamente muestra un iconito verde de 'conectado'.

conectado significa que además el servidor conserva una referencia de tí como cliente, y que lo añade a una colección (típicamente una tabla hash).
Por tanto ya estás en la sala 'Raíz', la colección global de clientes conectados al servidor...

Pero el servidor, puede querer gestionar la clección en trozos más pequeños, pongamos que si hay 10.000 clientes conectados al servidor, no sería muy útil todos respondiendo al mismo tiempo en una sola sala.

entonces el servidor puede optar por crear auytomáticamente 'salas' cuando una se satura.
Así dentro d ela clase servidor, podría existir la siguiente funcion:
Sala = funcion CrearSalaAuto( String Nombre, cliente Propietario, Entero NumMaxUsers)
   Sala s

   Si Salas.Existe(Nombre) = FALSE) luego
       s = Nueva sala(Nombre, Propietario, NumMaxUsers)
       Salas.Add(s)
       DispararEvento SalaCreada(s.Nombre)
       
       Devolver s
   Fin si
Fin funcion


Y la razón para crear una sala automática es repartir clientes, orque había chorrocientos... antes de ir a cambiar el código, dejamos como era el código previo, para esa función:
Sala = Funcion Conectar(Cliente Cli) Publico
       Si SalaRaiz.AdmiteClientes = TRUE luego
            Si SalaRaiz.Add(cli) = TRUE  // solo debería devolver false si ya existe un cliente con el mismo alias.
                Devolver SalaRaiz
            Fin si
       Fin si
Fin Funcion


Ahora vamos al código, modificando la función Conectar(), al servidor
Sala = Funcion Conectar(Cliente Cli) Publico
       Si (SalaRaiz.AdmiteClientes = TRUE) luego
           Si (SalaRaiz.Cantidad < 1500) luego
               Si (SalaRaiz.Add(cli) = TRUE)  // solo debería devolver false si ya existe un cliente con el mismo alias.
                   Devolver SalaRaiz
               Fin si
           Si no
               Hacer
                   String Nombre = Random(Chars(8))
                   Sala s = CrearSalaAuto(Nombre, Clientes.Item(0) , 1501) //cliente.Item(0), se supone que es el creador del servidor... un admin.
               Repetir mientras s.Nombre = "" // el nombre se crea al azar, si ya existe una con ese nombre falla, luego se reintenta. Lo razonable es que haya un ficherito con nombres de salas 'prefedinidas', que puedan tomarse en secuencia, manteniendo un puntero del último índice usado.
               
               // los clientes entre 1000 y 1500 se mueven a la nueva sala recién creada (por saturación de la previa), cuando llegue de nuevo a los 1500, se volverá a crear otra sala con 500 clientes...
                // También podría elegirse al azar a 500 clientes, pero esto podría dar lugar a que un cliente en repetidas ocasiones fuera movido a otra sala, Si los más antiguos, son los que permanecen ya saben que no serán movidos cuando haya un exceso de clientes en la sala, solo los más nuevos, y estos a su vez serán los más viejos en la siguiente sala... en definitiva, para el cliente esta simple opción parece menos molesta.
               Bucle para k desde 1000 hasta Clientes.Cantidad
                   Cliente c = Clientes.Item(k)
                   Clientes.Remove(k)
                   // Se notifica (sólo) a éste cliente que fue desconectado de la sala
                   c.SalaDesconectada(SalaRaiz.nombre)  //el porgrama cliente borrará el contenido de la ventana, lista de usuarios y mensajes.
                   s.Add(c) //en el método add se debe dispara un evento de 'usuario añadido', que notifica a todos los clientes de esa sala.
                     
                   // se notifica (solo) a este cliente que fue conectado a otra sala.
                   c.SalaConectada(s, s.Nombre)  // el programa cliente, toma la lista de clientes de la sala 's' y los lista y ahora los mensajes que esos usuarios publiquen se comparten solo entre los que tienen una referencia a la sala 's'
               Fin bucle
                               
               Salas.Add(s, s.Nombre)  // Añadimos la sala a la colección de salas.
               // informamos a todos los clientes suscritos al servidor de que hay una nueva sala disponible.
               DispararEvento SalaCreada(s.Nombre)

               s.add(Cli)  //el nuevo cliente que se acaba de conectar se añade a esta sala. y dispara un evneto que comunica a todios los clientes el alias del cliente recién conectado.
               //Cli.SalaConectada(s, s.Nombre) en la devolución de esta función haría lo mismo que en ese método.
               Devolver s //el cliente ahora recibe la sala 's', su programa luego de recibirlo, leerá los clientes conectados a ella y losmensajes de todos ellos se escribirán ahora ahí
           Fin si
       Fin si
Fin Funcion


Date cuenta que omito algunas comprobaciones, para no hacer el pseudocódigo demasiado enfangoso en detalles menores obvios ... es decir el nuevo lciente que se conecta debe verificarse si ya hay uno conectado con ese alias en la sala, y denegarle el acceso en tal caso con un código de error, que significa que 'ese alias ya existe en la sala (incluso mejor si se compara con la lista global.

Un método más propicio, sería no mover los clientes de la colección global (salaRaiz), sino que cuando, tras crear el Servidor se crea la salaRaiz, donde estén todos los clientes y una primera sala, donde se añaden los primeros 1000 clientes, cuando se llegue a 1000, se crea otra sala, y los siguientes se conectan a esa nueva sala... y todos siguen constando en la SALARaiz, para verificar que no hay repetido un alias en todo el servidor, esa sala entonces debería ser privada, nadie debe verla, salvo los admin.

Es decir cuando un cliente se conecta, primero se mira si se puede añadir a la salaRaiz, si no está allí su alias se añade, y luego se le añade a la sala 'actual' , o una al azar si se crean varias nada más generar el servidor, como ya sabemos que fue añadido a la salaraíz, su alias no está repetido, luego se podrá añadir a otra sala sin problemas.

Veamos ahora una función más del servidor... cambiar de sala.
Dado que el cliente tiene una referencia del Servidor, tiene acceso a la colección Salas (en modo lectura)... luego se puede listar cuando un cliente se conecta, pero cuando se crea una sala nueva, se notifica con un evento...(como se vió en la modificación de la función anterior).

Entero = Funcion ListarSalas(Out Listastring() NombreSalas)
    Dimensionar NombreSalas(0 a Salas.Cantidad-1)
     
   Bucle para k por cada sala s en Salas
       NombreSalas(k) = s.Nombre
   Fin bucle
   
   Devolver NombreSalas.Length // ó Salas.Cantidad
Fin funcion


Ahora otra función (del servidor) para cambiar de sala, a petición del Cliente:
Buleano = Funcion CambiarDeSala(String Nombre, Cliente Cli)
   Sala s
   Si (Salas.Existe(nombre) = TRUE)
       Cli.Sala.Desconectar //Esto provoca un evento clienteDesconectado en dicha sala, que informa a todos los clientes d ela sala de la desconexión (solo informa del Alias)
       // Sala.Desconectar invocaría internamente a Clientes.Remove(Cli) Dentro de la instancia Sala
       s = Salas.GetSala(Nombre) //El servidor tiene público la colección Salas, y esta función está dentor de la clase Servidor...
       s.Add(Cli)
       
       Devolver TRUE
   Fin si
Fin funcion



Ahora veamos como sería una clase Cliente (no confundir con el programa Cliente, el programa tiene admeás una instancia de esta clase Cliente, que identifica al usuario y le permite hacer ciertas cosas):

Un cliente simplificado:
Tiene un alias, una conexión con el servidor, una función publicar y una referencia
Clase Cliente
   Sala Sala ConEventos Oculto
   Servidor Conex ConEventos Privado
 
   String Propiedad Alias  <---- público
   String Propiedad HashId <----- privado, se genera automáticamente cuando se crea la instancia de la clase cliente.
   String Propiedad SoloLectura Privilegios Oculto
   Buleano Propiedad SoloLectura Oculto Publico
 
   Funcion Nuevo(String Nombre, Out Buleano Ok) Publico // el que se crea con un nuevo cliente genérico.
       Alias = Nombre
       HashId= CrearHash(Alias, TimeNow, NumRandom(100.000.00, 999.999.999))
       Privilegios = DefaultPrivilegios

       Conex = ConectarAServidor(Los datos de conexión)
       Si Conex.Existe Luego OK = TRUE
   Fin Funcion

   Funcion Nuevo(String Nombre, Buleano Visible, String Privileg) Privado // el que se crea con un admin, o el cliente creador del servidor que lo arranca y crea salas, etc...
       Alias = Nombre
       Oculto = Visible
       HashId= CrearHash(Alias, TimeNow, NumRandom(100.000.00, 999.999.999))
       Privilegios = Privileg

       // El cliente que crea esta instancia, tiene otro medios para realizar la conexión al servidor, porque es el que arranca el servidor y crea la NUEVA instancia del mismo.
   Fin Funcion

   Funcion CambiarPrivilegios(String Privileg) Oculto
       Privilegios = Privileg
       Sala.VerificarPrivilegios(Privileg)
   Fin Funcion

   // Evento que salta cuando se desconecta mediante Sala.Desconectar
   Funcion Sala_Desconectado(String Nombre)
       Borrar lista de clientes (usuarios),
       Borrar mensajes de la pizarra (textbox u otro objeto)
       //Obtener la lista de salas
      ListaString() Nombres =  Conex.ListarSalas(NumSalas)
      Bucle para k desde 0 a NumSalas-1
           ListboxSalas.Add(Nombres.Nombre)  // añade a un listbox, la lista de salas
       Fin bucle
   Fin Funcion

   // Este podría ser otro evento de la clase Sala, que se dispara cuando se añade un cliente a la sala
   Funcion Sala_ClienteConectado(String Alias)
       ListboxUsers.Add(Alias)
       Textbox.Add(Alias, " se añadió a la sala", Time.Tostring)
   Fin funcion

   // Este podría ser otro evento de la clase Sala, que se dispara cuando se desconecta un cliente de la sala
   Funcion Sala_ClienteDesconectado(String Alias)
       ListboxUsers.Remove(Alias)
       Textbox.Add(Alias, " se fue de la sala", Time.Tostring)
   Fin funcion

   // este podría ser un evento de la instancia del servidor...
   Funcion Conex_SalaCreada(Sala s)
       ListboxSalas.Add(s.Nombre)
       Textbox.Add("Se creó una nueva sala", s.Nombre, Time.Tostring)
   Fin funcion
Fin clase




Finalmente un ejemplo de lo que podria ser la clase Sala...
Clase Sala
   TablaHash Clientes Oculto
   Cliente Propietario Oculto  // la idea es que solo el propietario o un admin, pudiera eleiminar la sala.
   Servidor Conex
   Entero MaxUsers Oculto
   String NombreSala Publico

   Entero = Propiedad SoloLectura NumClientes Publico
       Numclientes = Clientes.Cantidad    
   Fin Propiedad
 
   Evento ClienteConectado(String Alias)
   Evento ClienteDesconectado(String Alias)
   Evento NuevoMensaje(String Mensaje, string Alias, String hora, etc...)

   // Todos los clientes suscritos a esta instancia recibirán el evento y ninguno más que estos.
   Buleano = Funcion Publicar(String Mensaje, String Hora, etc...)
        DispararEvento NuevoMensaje(Mensaje, Alias, Hora, etc...)
   Fin Funcion

   Sala = Funcion Add(Cliente NewCli) Publico
       Si (Clientes.Cantidad < MaxUsers) luego
           Si (Clientes.Existe(NewCli.Alias, NewCli.HashId) = FALSE) luego
               Clientes.Add(NewCli)
               DispararEvento ClienteConectado(NewCli.Alias)
           Fin si
       Fin si
   Fin funcion

   Buleano = Funcion Remove(Cliente Cli)
        Si (Clientes.Existe(Cli.Alias, Cli.HashId) = TRUE) luego
           Clientes.Remove(Cli)
           DispararEvento ClienteDesconectado(Cli.Alias)
           Devolver TRUE
       Fin si
   Fin funcion

   Sala = Funcion Nuevo(Cliente Propietario, String Nombre, Entero NumMaxUsers, Servidor Conexion)
         Si (Conexion.Clientes.Existe(Propietario.Alias, Propietario.HashId) = TRUE) luego
             Conex = Conexion
             MaxUsers = NumMaxUsers
             Clientes = Nueva TablaHash(NumMaxUsers)
             Clientes.Add(Propietario)
             Nombresala = Nombre
                         
             Devolver This
         Fin si
   Fin Funcion

   ...más funciones, propiedas, etc.. por ejemplo cambiar privilegios en la sala a un cliente...
Fin Clase



Es un código al vuelo, así rápido así que estará lleno de imprecisiones erroes, y diferencias (en un sitio llamo a un evento de una manera y luego en su clase la nombro de otra), es razonable escribiendolo sobre la marcha...

...espero sin embargo que sirva para que te quede claro varias cosas:
--- Que una sala, es tan solo una colección de clientes suscritos a una misma instancia, y que por tanto comparten los eventos de esa única instancia entre ellos.
--- Que el servidor mantiene la lista de salas, que es simplemente otra colección de instancias de sala.
--- que el servidor puede crear una sala, o varias, incluso de modo automártico si una sala se satura pongamos al 75% de su capacidad, desplazando (también automáticamente) usuarios a la otra sala recién creada.
--- Que el servidor puede permitir a un cliente crear una sala, bajo demanda (petición). aunque lo normal es que lo creen los admins o usuarios con privilegios.
--- Que los privilegios, aunque no se ha hablado apenas de ellos, son una simple lista de textos, algo como: "CreateSala, MoveToAnySala, ConnecToAnySala, DisconnectToSala, ListUsersInSala, ListSalasInServer, ChangePrivileges, etc..." Incluso un textomás abreviado con mnemónicos si lo prefieres: "cre, mov, con, dis, liu, lis, cha, etc..."

...y bueno si no te enteras, pués ya más no se puede hacer....