[JAVA] outputstreams van sockets doen raar ...

Pagina: 1
Acties:

  • Feyd-Rautha
  • Registratie: November 2001
  • Laatst online: 02-08-2025
Ik heb al enkele topics over mijn chat client-server systeem geopend, en hier is er weer eentje. :)

Ik zit met het volgende, raar probleem:

Mijn client kan moeiteloos een connectie maken met mijn server. Die server stuurt dan een 'synchronisatie'-bericht terug naar alle geconnecteerde clients om de juiste userlijst te bekomen. Dit werkt perfect, ook bij het disconnecten.

Maar wanneer een client nu zijn nickname wil veranderen, doet hij dit door middel van een 'nickchange'-bericht waarin zijn nieuwe nick wordt meegegeven. De server analyseert dit, verandert de nick in zijn userpool en mulicast terug een 'synchronisatie'-bericht naar alle clients.
Het probleem zit nu juist bij die ene synchronisatie:

De server genereert het 'synchronisatie'-bericht perfect (dus met de juiste nickname); wanneer dat bericht bij de client toekomt, is de nickname die zou moeten veranderd zijn, terug zoals oorspronkelijk :? .

Misschien eventjes volgend code-fragment om alles te verduidelijken

CLIENT: dit wordt uitgevoerd wanneer de client op OK klikt bij het dialoogvenster om zijn nickname te veranderen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void cmdOk_actionPerformed(ActionEvent e)
  {
    String[] newNick = new String[1];
    newNick[0] = txtNickname.getText();
    // een NICKCHANGE-actionmessage aanmaken
    AbstractMessage nickMsg = new ActionMessage(ownerWindow.getThisUser(),
                                                null,
                                                shared.Action.NICKCHANGE,
                                                newNick);

    ownerWindow.getSender().send(nickMsg);

    this.dispose();
  }


SERVER: De server zal dit bericht ontvangen en 'parsen':

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public void parseMessage(AbstractMessage m) throws IOException
  {
    if (m instanceof ActionMessage)
    {
      ActionMessage actionMsg = (ActionMessage)m;

      switch (actionMsg.getAction())
      {
        // DISCONNECT: de betreffende user verwijderen en terug SYNCHRONIZEREN
        case Action.DISCONNECT:
              users.removeUser(actionMsg.getSource().getNickname());
              synchMsg = new ActionMessage(null, null, Action.SYNCHRONISE, users.toArrayUsers());
              parseMessage(synchMsg);
              break;

        // SYNCHRONIZE: een actionmessage broadcasten met alle connected users
        case Action.SYNCHRONISE:
              for (int i=0; i<users.getUserCount(); i++)
              {
                actionMsg.setDestination(users.getUser(i));
                sender.send(actionMsg);
              }
              break;

        // NICKCHANGE: de nickname van een user veranderen
        case Action.NICKCHANGE:
              User u = users.getUser(actionMsg.getSource().getNickname());
              u.setNickname(actionMsg.getAttachment(0));

              synchMsg = new ActionMessage(null, null, Action.SYNCHRONISE, users.toArrayUsers());

              /*****DEBUG*************/
              for (int i=0; i<users.getUserCount(); i++)
                System.out.println(users.getUser(i));
              /******END DEBUG********/
              
              parseMessage(synchMsg);
              break;
      }
    }
    .....
}


Zoals je zit zal eerst de nickchange worden uitgevoerd, een nieuwe synchronise-bericht aangemaakt worden en terug geparsed en tenslotte verzonden naar alle clients. Die DEBUG-sectie toont de juiste, aangepaste, nicknames

CLIENT: Dit 'synchronisatie'-bericht komt toe bij de client:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
msg = (AbstractMessage)objin.readObject();

          if (msg != null)
          {
            // message doorsturen naar de parser

          /************************
            HIER LOOPT HET MIS !!*/

          /***********************/

            System.out.println("message received: " + msg);

          /*******DEBUG -- PRINT DE ATTACHMENTS***********/
          String[] att = ((ActionMessage)msg).getAttachment();
          for (int i=0; i<att.length; i++)
            System.out.println(att[i]);
          /******END DEBUG*****************************/
            
            parser.parseMessage(msg);


Ik heb aangeduid waar het misloopt.

wat output tijdens nickchange:
server
Listening for messages ...
serverSocket.accept() timeout
Listening for connection ...
Message received: *** ACTION: Nickchange
Feyd-Rautha
serverSocket.accept() timeout
Listening for connection ...
Een nickchange-bericht is ontvangen met de juiste (aangepaste) nickname als 'attachment'
client
message received: *** ACTION: Synchronised
D5E0E262.kabel.telenet.be
Een 'synchronisatie'-bericht komt toe, maar met de verkeerde nickname


Zijn er hier mensen die al eens hetzelfde probleem hebben voorgehad en die me zouden kunnen helpen of tips geven. Ik heb me hier al op rot-gezocht (sorry voor mijn taalgebruik :P ).

I must not fear. Fear is the mind-killer. Fear is the little-death that brings total obliteration. I will face my fear. I will permit it to pass over me and through me. Where the fear has gone there will be nothing. Only I will remain.


Verwijderd

Volgens mij gaat t hier fout:

Java:
1
2
User u = users.getUser(actionMsg.getSource().getNickname());
u.setNickname(actionMsg.getAttachment(0));


wat je volgens mij zou moeten doen is t volgende:

Java:
1
2
3
User u = users.getUser(actionMsg.getSource().getNickname());
u.setNickname(actionMsg.getAttachment(0));
users.replaceUser( users.getUser(actionMsg.getSource().getNickname()) , u);

replaceUser moet je dan nog even maken

  • Feyd-Rautha
  • Registratie: November 2001
  • Laatst online: 02-08-2025
mm... nogtans, nadat ik de user heb veranderd, print ik alle users terug af en de juiste wordt getoond. Ik heb ook al daarop zitten denken.

Maar zal het toch maar eens proberen

I must not fear. Fear is the mind-killer. Fear is the little-death that brings total obliteration. I will face my fear. I will permit it to pass over me and through me. Where the fear has gone there will be nothing. Only I will remain.


  • Postman
  • Registratie: Februari 2000
  • Laatst online: 15-08 20:11
Feyd-Rautha schreef op 05 november 2002 @ 20:23:
mm... nogtans, nadat ik de user heb veranderd, print ik alle users terug af en de juiste wordt getoond.
Gaat het dan niet ergens anders mis?? Stuurt je client misschien niet nog 1 bericht waarin de oude nick staat??

  • Feyd-Rautha
  • Registratie: November 2001
  • Laatst online: 02-08-2025
Ik heb het eindelijk gevonden !! :) :)

* voor de geinteresseerden: *
bij mijn 'message-parser' van mijn server, had ik 1 AbstractMessage synchMsg gedeclareerd. Deze 'synchMsg' gebruikte ik voor zowel bij de synchronisatie van een CONNECTj-aanvraag alsook voor een synchronisatie bij NICKCHANGE-aanvraag. (zie voorbeeldcode bij de starterpost)
Ik heb nu voor ieder synchronisatie-msg een nieuwe variabele aangemaakt en nu werkt het.

Maar ik zit nu ergens met memory-leaks tot en met, want waneeer ik wil disconnecten en het client-programma afsluiten, gaat alles voor een tijdje heeeeel traag.

I must not fear. Fear is the mind-killer. Fear is the little-death that brings total obliteration. I will face my fear. I will permit it to pass over me and through me. Where the fear has gone there will be nothing. Only I will remain.


  • whoami
  • Registratie: December 2000
  • Laatst online: 29-08 15:58
Memory leaks in Java ? Ik dacht dat dat niet kon? Een java prog draait toch in de JVM en die heeft toch een garbage collector? De virtual machine (garbage collector eigenlijk) is er dan voor verantwoordelijk dat objecten die geallocceerd werden en niet meer nodig zijn ge-freed/destroyed worden.

https://fgheysels.github.io/


  • Feyd-Rautha
  • Registratie: November 2001
  • Laatst online: 02-08-2025
ik weet niet precies of het memory-leaks zijn, of iets anders.
'k Ga toch eens gans mijn proggel herbekijken....

Het zal ook nog efficienter moeten gaan met JDK1.4 (waarin je die selector-objecten hebt ). Nu overloop ik in een thread alle clients om te zien of ze een message hebben gestuurd.

I must not fear. Fear is the mind-killer. Fear is the little-death that brings total obliteration. I will face my fear. I will permit it to pass over me and through me. Where the fear has gone there will be nothing. Only I will remain.


  • PommeFritz
  • Registratie: Augustus 2001
  • Laatst online: 10-07 04:13

PommeFritz

...geen friet

--> whoami: Java Memory Leaks :P

FireFox - neem het web in eigen hand


  • bazzs2001
  • Registratie: April 2002
  • Laatst online: 13-06 11:18

bazzs2001

je moet knagen wat lekker is

_/-\o_ goed verhaaltje, in het vervolg toch iets meer referenties weggooien :Y) 8)7

groeten


  • whoami
  • Registratie: December 2000
  • Laatst online: 29-08 15:58
Tja, dat is natuurlijk logisch, dat zolang er een referentie is naar dat object, dat het niet gedealloceerd wordt. Als je in C++ bv een object dat aan een hashtable ofzo hangt niet meer nodig hebt, en je verwijderd het niet van die hashtable en delete het niet, dan heb je zogezegd ook een memory leak.
Trouwens, als het programma afgesloten wordt, dan wordt alle geheugen vrijgegeven (ook de memory leaks).
En ik denk trouwens niet dat je 'het traag afsluiten van een programma' een symptoon kunt noemen van een memory leak.

https://fgheysels.github.io/


  • AaroN
  • Registratie: Februari 2001
  • Laatst online: 16-08-2023

AaroN

JayGTeam (213177)

om whoami aan te vullen:
memory leaks zullen er op den duur voor zorgen dat het systeem out_of_memory zal geraken. Het systeem zal dus moeten rebooten, wat bijvoorbeeld voor servers zwaar irritant is. Als jouw programma langzaam sluit ofdat het lang duurt voordat alles weer normaal loopt, zal de JVM waarschijnlijk druk bezig zijn met het cleanen van jouw zooi :P
Als JVM klaar is, moet het zo zijn dat er geen memory meer gebruikt worden door een of andere instantie van een Java programma dat heeft gedraaid.

JayGTeam (213177)


  • Bobco
  • Registratie: Januari 2001
  • Laatst online: 30-10-2023

Bobco

I used to dream about Verona.

AaroN schreef op 07 november 2002 @ 11:38:
om whoami aan te vullen:
memory leaks zullen er op den duur voor zorgen dat het systeem out_of_memory zal geraken. Het systeem zal dus moeten rebooten, wat bijvoorbeeld voor servers zwaar irritant is. Als jouw programma langzaam sluit ofdat het lang duurt voordat alles weer normaal loopt, zal de JVM waarschijnlijk druk bezig zijn met het cleanen van jouw zooi :P
Als JVM klaar is, moet het zo zijn dat er geen memory meer gebruikt worden door een of andere instantie van een Java programma dat heeft gedraaid.
Mmh, is denk ik niet zo 1-2-3 te zeggen. Als je een programma sluit hangt het nogal af van de clean-up processing die je dan doet. Als je een applicatie stopt door gewoon System.exit(0) te doen dan zou er helemaal niet zoveel tijd nodig hoeven te zijn om te stoppen.

Ik denk (en dat weet ik dus ook niet zeker) dat de meeste JVMs niets doen aan Garabage Collection zolang ze nog voldoende geheugen over hebben om de applicatie te kunnen laten draaien. Het lijkt me dan ook onwaarschijnlijk dat een JVM bij het afsluiten opeens nog ruimte vrij gaat maken die toch niet meer gebruikt kan worden.

With the light in our eyes, it's hard to see.


  • PommeFritz
  • Registratie: Augustus 2001
  • Laatst online: 10-07 04:13

PommeFritz

...geen friet

Er is een structureel probleem met Garbage Collection in Java: voor zover ik weet gebeurt het alleen maar als er "tijd" voor is. Dat wil zeggen, als je applicatie niet bezig is.
Dus.... stel dat je een server app hebt die het opeens heel druk heeft, en veel geheugen alloceert, dan zal de GC niet in actie komen om "loze" referenties op te ruimen - want je programma is nog druk bezig en de GC krijgt geen CPU cycles.
Dus juist op het moment dat je hem hard nodig hebt, doet ie het niet.
Blijf dus donders goed opletten met je object referenties, zeker in een long-running proces.

FireFox - neem het web in eigen hand


  • Bobco
  • Registratie: Januari 2001
  • Laatst online: 30-10-2023

Bobco

I used to dream about Verona.

PommeFritz schreef op 07 November 2002 @ 22:19:
Er is een structureel probleem met Garbage Collection in Java: voor zover ik weet gebeurt het alleen maar als er "tijd" voor is. Dat wil zeggen, als je applicatie niet bezig is.
De JVM specificatie zeg bijzonder weinig over Garbage Collection. Er is natuurlijk altijd die System.gc() aanroep die je kunt doen, maar ook dat biedt geen garantie dat er inderdaad opgeruimd wordt.

Overigens moet je dit 'probleem' wel in het juiste perspectief zien. De JVMs die ik ken doen wel degelijk aan Garbage Collection, ook als er gewerkt wordt door de applicatie. Bovendien zorgt een goed geschreven programma er zelf voor dat resources worden vrijgegeven als ze niet meer nodig zijn. Als je uitgaat van dat laatste moet je wel heel erg exorbitante programma's schrijven om een JVM out-of-memory te laten gaan.

De JVM kan immers aan het OS om meer geheugen vragen en pas op het moment dat dat niet meer lukt wordt Garbage Collection echt een noodzaak. Op een beetje moderne machine heb je het dan al wel over heeeel veel objecten en kun je je afvragen of het ontwerp/implementatie wel OK is.

Garbage Collection is handig, maar het ontslaat de programmeur niet van de verantwoordelijkheid om goed om te gaan met resources.

With the light in our eyes, it's hard to see.

Pagina: 1