Tema destacado:
Autor
|
Tema: Problema lógico... [Otro mas..] (pero que cabezota que soy...) (Leído 1,995 veces)
|
|
Debci
|
Hola a todos, estoy depurando mi aplicacion de red... una tool util que pronto pondre en forma de source y binario en el foro.
Es una aplicacion cliente-servidor que usa sockets, threads y demas...
Bueno uso un sistema de enumeración para ordenarlos en la memoria y poder identificarlos.
La cosa esta en lo siguiente:
Cuando un cliente se conecta al servidor:
Añado 1 al contador (contador++;)
Cuando se desconecta, disminuyo 1 (contador--;)
Pero ocurre el siguiente fallo:
Si abro dos, les doy como id 1 y 2.
Si se va uno, disminuyo y el contador esta en 1 (contador - 1 = 2) y si entra otro se le asigna el 2, ahora tengo dos con el el identificador 2, y uno se remplaza al otro en la tabla de hash.
Me planteé hacerlo que nunca disminuya, pero ocurre el siguiente fallo, cuando quiero hacer un cast a todos, las id que se han desconectado pero sin embargo todavia estan registradas ya no tiene un objeto guardado y produce expeciones cosa mala.
Que puedo hacer?
Saludos
|
|
|
|
|
En línea
|
|
|
|
|
|
|
Debci
|
Lo que esta pasando es que no tienes en cuenta la posibilidad de que dos hilos accedan a ese contador a la vez y es lo que esta pasando, en cada uno de los hilos de conexion cada vez que intentes decrementar o incrementar ese contador deberas hacerlo dentro de un bloque synchronized de forma de que solo un hilo puede estar accediendo a esa variable en un determinado instante, es decir, has de tratarlo como parte critica del codigo.
Un saludo
Y así es, el problema es que el contador no es lógico, segun mi punto de vista. Me explico: Debo inventar un sistema para que valla ocupando los puesto libres que van dejando los otros clientes. Pero no me figuro como hacerlo. Saludos
|
|
|
|
|
En línea
|
|
|
|
Novlucker
Ninja y
Ex-Staff
Desconectado
Mensajes: 10.239
Yo que tu lo pienso dos veces
|
Siempre digo lo mismo, no se nada de java, pero las dos veces anteriores le atine!, igual esto es de lógica  No uses un contador ... Al conectarse alguien: Si la tabla esta vacía, simplemente agregas un nuevo ID valor 1 Si la tabla NO esta vacía, la recorres y verificas si algun elemento apunta a un objeto null, si el objeto es null, lo pisas con uno nuevo, si llegas el final sin encontrar un null, agregas un nuevo elemento con id size+1 Al desconectarse alguien: Pisas el valor de la tabla con un objeto null Con esto tendrás una tabla con elementos "válidos" y nulos, así que solo deberás de filtrar los nulos a la hora de trabajar Saludos 
|
|
|
|
« Última modificación: 30 Diciembre 2009, 17:33 por Novlucker »
|
En línea
|
Contribuye con la limpieza del foro, reporta los "casos perdidos" a un MOD XD http://twitter.com/novlucker "Hay dos cosas infinitas: el Universo y la estupidez humana. Y de la primera no estoy muy seguro." Albert Einstein
|
|
|
|
Debci
|
Siempre digo lo mismo, no se nada de java, pero las dos veces anteriores le atine!, igual esto es de lógica  No uses un contador ... Al conectarse alguien: Si la tabla esta vacía, simplemente agregas un nuevo ID valor 1 Si la tabla NO esta vacía, la recorres y verificas si algun elemento apunta a un objeto null, si el objeto es null, lo pisas con uno nuevo, si llegas el final sin encontrar un null, agregas un nuevo elemento con id size+1 Al desconectarse alguien: Pisas el valor de la tabla con un objeto null Con esto tendrás una tabla con elementos "válidos" y nulos, así que solo deberás de filtrar los nulos a la hora de trabajar Saludos  Era justo lo que necesitaba ^^ A veces necesito un empujoncito con la logica de algun algoritmo xD Saludos
|
|
|
|
|
En línea
|
|
|
|
|
|
Novlucker
Ninja y
Ex-Staff
Desconectado
Mensajes: 10.239
Yo que tu lo pienso dos veces
|
panaka, lo que ocurre es que el problema del post no es ese, su problema es que va llenando la tablahash y dado que utilizaba un contador, al disminuir el valor acumulado en este, se corría el riesgo de pisar "antiguos elementos" ... ej: Tabla por defecto ... Contador == 2 ID 1 2 3
| Valor Objeto Objeto Objeto
|
Ingresa un elemento ... Contador == 3 Se va el elemento 1... Contador == 2 En esta situación, dado que el ingresa los nuevos elementos en el Contador+1, en el próximo ingreso se pisa el valor de 3, es decir, más allá de que se este trabajando con estructuras sincronicas o no, el problema es de lógica  Saludos
|
|
|
|
« Última modificación: 31 Diciembre 2009, 01:18 por Novlucker »
|
En línea
|
Contribuye con la limpieza del foro, reporta los "casos perdidos" a un MOD XD http://twitter.com/novlucker "Hay dos cosas infinitas: el Universo y la estupidez humana. Y de la primera no estoy muy seguro." Albert Einstein
|
|
|
|
Leyer
|
Me planteé hacerlo que nunca disminuya, pero ocurre el siguiente fallo, cuando quiero hacer un cast a todos, las id que se han desconectado pero sin embargo todavia estan registradas ya no tiene un objeto guardado y produce expeciones cosa mala.
si estas usando un hashTable la verdad no me explico eso 
|
|
|
|
|
En línea
|
|
|
|
|
Debci
|
panaka, lo que ocurre es que el problema del post no es ese, su problema es que va llenando la tablahash y dado que utilizaba un contador, al disminuir el valor acumulado en este, se corría el riesgo de pisar "antiguos elementos" ... ej: Tabla por defecto ... Contador == 2 ID 1 2 3
| Valor Objeto Objeto Objeto
|
Ingresa un elemento ... Contador == 3 Se va el elemento 1... Contador == 2 En esta situación, dado que el ingresa los nuevos elementos en el Contador+1, en el próximo ingreso se pisa el valor de 3, es decir, más allá de que se este trabajando con estructuras sincronicas o no, el problema es de lógica  Saludos Exacto, lo que yo quiero es que llene el hueco que queda vacio, en este caso el id 1. Pero no me figuro, porque he predefinido uno de los parametros de la hashtable como Socket, intente hacer lo que me aconsejasteis, cojer y meterle null cuando se desconectase, pero no me deja darle null, si pudiese darle null, luego recorreria todo el vector y veria cualos son null y devolveria un mapa con las vacias para que la secuencia escojiese la mas pequeña de esas y se lo autoasignase. Pero no se darle null :s Saludos Saludos
|
|
|
|
|
En línea
|
|
|
|
Novlucker
Ninja y
Ex-Staff
Desconectado
Mensajes: 10.239
Yo que tu lo pienso dos veces
|
Ok, lo que ocurre es que mi sugerencia venía de parte de C# por ejemplo (la similitud con Java es monstruosa!), donde si bien las hashtables no pueden tener keys null, si pueden tener valores null, pero ahora revisando la documentación de java ... http://java.sun.com/j2se/1.4.2/docs/api/java/util/Hashtable.htmlput public Object put(Object key, Object value)
Maps the specified key to the specified value in this hashtable. Neither the key nor the value can be null. Entonces hay que descartar esa opción. Alternativa que se me ocurre, llevar un simple array de booleanos en paralelo, donde index +1 = ID y valor true o false según este o no conectado. Entonces al igual que antes recorres el array, si el elemento 0 es false (por ej), entonces el ID1 esta vacío, cambias valor a true, y en la hashtable asignas objeto  Por otra parte, no hay método para cambiar tamaño de array luego de declarado?  (obviamente no me refiero a copiar el array en otro con length+1) Saludos
|
|
|
|
|
En línea
|
Contribuye con la limpieza del foro, reporta los "casos perdidos" a un MOD XD http://twitter.com/novlucker "Hay dos cosas infinitas: el Universo y la estupidez humana. Y de la primera no estoy muy seguro." Albert Einstein
|
|
|
|
Debci
|
Ok, lo que ocurre es que mi sugerencia venía de parte de C# por ejemplo (la similitud con Java es monstruosa!), donde si bien las hashtables no pueden tener keys null, si pueden tener valores null, pero ahora revisando la documentación de java ... http://java.sun.com/j2se/1.4.2/docs/api/java/util/Hashtable.htmlput public Object put(Object key, Object value)
Maps the specified key to the specified value in this hashtable. Neither the key nor the value can be null. Entonces hay que descartar esa opción. Alternativa que se me ocurre, llevar un simple array de booleanos en paralelo, donde index +1 = ID y valor true o false según este o no conectado. Entonces al igual que antes recorres el array, si el elemento 0 es false (por ej), entonces el ID1 esta vacío, cambias valor a true, y en la hashtable asignas objeto  Por otra parte, no hay método para cambiar tamaño de array luego de declarado?  (obviamente no me refiero a copiar el array en otro con length+1) Saludos Para hacerlo de esa manera, mejor usar hashTable jeje, mira voy a intentar algo asi: HashTable<Integer, Integer> listanegra; Si se desconecta un cliente, se añade a la lista negra y añade la key por orden, y el otro valor el id que deja libre, luego en cada asignacion de id, recorro la hashTable y cojo los valores libres que van quedando disponibles. En teoria funcionaria no? Pero se me presenta una duda, como hago para cojer siempre el valor libre mas pequeño? Saludos
|
|
|
|
|
En línea
|
|
|
|
Novlucker
Ninja y
Ex-Staff
Desconectado
Mensajes: 10.239
Yo que tu lo pienso dos veces
|
No creo que sea mejor usar un hashtable, para lo que planteo tendrías una simple lista, para lo que comentas tendrías una tabla que además no se aprovecha, y con eso voy a lo siguiente que preguntas ... Si se desconecta un cliente, se añade a la lista negra y añade la key por orden, y el otro valor el id que deja libre, luego en cada asignacion de id, recorro la hashTable y cojo los valores libres que van quedando disponibles. Para eso deberías de recorrer todas las claves de la hashtable (blacklist) para así determinar cual es la más pequeña .. Mín = Primer elemento Segundo elemento menor que Mín? Si - Mín = Segundo elemento No - Siguiente O por "fuerza bruta", revisando si una key esta en la hashtable hasta encontrar la primera coincidencia o haber comparado N elementos == Hashtable.size. No lo veo más sencillo  Saludos P.D: creo que ya he publicado más post de los debidos en este subforo XD
|
|
|
|
|
En línea
|
Contribuye con la limpieza del foro, reporta los "casos perdidos" a un MOD XD http://twitter.com/novlucker "Hay dos cosas infinitas: el Universo y la estupidez humana. Y de la primera no estoy muy seguro." Albert Einstein
|
|
|
|
Debci
|
Nada que no sale, lo he intentado con un array y ahora con hashTable y nada: Metodo de busqueda antes de asignar while (true) { try { System.out.println("Esperando conexiones..."); Socket zombie = socketServidor.accept(); idZombie++; for(int i = 1; i < listaNegra.size(); i++) { System.out.println(listaNegra.get(i)); } if(listaNegra.isEmpty()) { System.out.println("Nuevo zombie añadido a la BotNet: " + idZombie + "\n"); vectorZombies.put(idZombie, zombie); nuevoZombie = new ControlBots(zombie, "Bienvenid@ a la red zombie!", idZombie); }else if(borrado) { System.out.println("Asignando un id disponible...\n"); System.out.println("Nuevo zombie añadido a la BotNet: " + listaNegra.get(contador) + "\n"); vectorZombies.put(listaNegra.get(contador), zombie); nuevoZombie = new ControlBots(zombie, "Bienvenid@ a la red zombie!",listaNegra.get(contador)); }else{ System.out.println("Nuevo zombie añadido a la BotNet: " + idZombie + "\n"); vectorZombies.put(idZombie, zombie); nuevoZombie = new ControlBots(zombie, "Bienvenid@ a la red zombie!", idZombie); } nuevoZombie.start(); Servidor.slider.setMaximum(idZombie); Servidor.numBots.setText(idZombie.toString()); borrado = false; } catch (IOException ex) { Logger.getLogger(ThreadEjecución.class.getName()).log(Level.SEVERE, null, ex); } } Metodo que uso cuando un cliente se desconecta: System.out.println("ADIOS!"); contador++; ThreadEjecución.listaNegra.put(contador, id); ThreadEjecución.RenovarDatos(); ThreadEjecución.borrado = true; Y todo bien, creo nuevos clientes, los tira adelante, pero cuando borro uno, y intento crear otro: Exception in thread "Thread-1" java.lang.NullPointerExceptionPorqueeeeeee Saludos
|
|
|
|
|
En línea
|
|
|
|
|
Leyer
|
P.D: creo que ya he publicado más post de los debidos en este subforo XD
 y asi bueno ya probaste utilizar un vector<usuario> vector <usuario>(); es decir que la ID estara interna al obj usuario es decir usuario.getID(); la cual puedes optenerla como la IP del usuario o alguna otra ID que le asignes y bueno cuando se desconecte uno solo seria Server.vector.remove(this); este estara en el obj usuario asi que cuando agas "this" eliminara ese usuario del vector y asi no te daria problemas es seguro while(true){ try { connector = serverConnector.accept(); userConnected = new ThreadUserConnected(this,connector); System.out.println("> Nuevo usuario conectado IP: "+connector.getInetAddress()+" L: "+connector.getLocalPort()); vectorOfConnectedUsers.addElement(userConnected); try { Thread.sleep(200); } catch (InterruptedException e) {System.err.println(e);System.exit(0);} vectorOfConnectedUsers.get(user).sendMessage(content.Constant._SERVERNAME,"Estas Conectado! ",Constant._SERVERFONT,Constant._SERVERSTYLE,Constant._SERVERCOLOR); user++; } catch (IOException e) {System.err.println(e); System.exit(0); } catch (Exception e) { content.Util.showException(this.getClass().getName(), "Error",e.toString()); } }
|
|
|
|
« Última modificación: 31 Diciembre 2009, 19:02 por LEYER »
|
En línea
|
|
|
|
|
Debci
|
Ese vector no es mas que una lista negra donde voy metiendo los que se desconectan, meto un id sumatoria (1,2,3,4,5...) como key y el otro valor integer el id que queda libre para asignarle a otro.
Saludos
|
|
|
|
|
En línea
|
|
|
|
|
|