[Java] Meerdere plain XML versturen over 1 socket

Pagina: 1
Acties:

  • b19a
  • Registratie: September 2002
  • Niet online
Beste Tweakertjes, ik zit met een probleempje mbt tot sockets. Ik ben hobbymatig een programma aan het ontwikkelen waarmee je je gemaakte uren kunt registreren. Het programma wat door meerdere mensen gebruikt gaat worden maakt een verbinding met de database om data te lezen/schrijven. Momenteel gebruik ik vanaf de clients direct een MySQL verbinding, maar dat is niet de juiste manier lijkt me aangezien gebruikertjes met de login allerlei ongewenste activiteiten kunnen bedrijven in mijn database. Daarom mijn idee om er een Java server tussen te gooien welke de gebruikers in staat stelt de door hun vereiste acties uit te voeren. Communicatie tussen server <-> client zal met XML documenten moeten gebeuren aangezien het volgende project onder andere van deze server gebruik moet gaan maken. Ik ben begonnen met me te verdiepen in de werking van sockets maar ik loop op een probleem. Ik gebruik JDOM om XML te parsen en aan te maken, ik gebruik de XMLOutputter klasse voor het verzenden van de data en SAXBuilder voor het inlezen van de data. Als ik vervolgens 2 XML bestanden wil verzenden over de socket (ik wil de verbinding open houden zolang de gebruiker aan het werk is) dan krijg ik de volgende foutmelding als de client het tweede bestand wil sturen:
Java:
1
2
3
4
5
java.io.IOException: Stream closed
    at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:145)
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:189)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:235)
...


De code op de server:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    public static void handleSocket(Socket incoming) throws IOException {
        //incoming.setKeepAlive(true); heeft geen effect
        
        SAXBuilder builder;
        XMLOutputter xmlout;
        Document doc;
        BufferedInputStream reader;
            try {
                reader = new BufferedInputStream(incoming.getInputStream());
                builder = new SAXBuilder(true);
                doc = builder.build(reader);
                reader.close();
                                
                System.out.println("Eerste xml ontvangen, bezig met ontvangen van tweede...");
                
                reader = new BufferedInputStream(incoming.getInputStream());
                builder = new SAXBuilder(true);
                doc = builder.build(reader);
                reader.close();
            } catch(Exception e) {
                e.printStackTrace();
            }
    incoming.close();
    }


En dan de client:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
            client=new Socket("localhost",8189);
            client.setKeepAlive(true);// ook deze heeft geen effect
            BufferedOutputStream outstream;
            
            outstream=new BufferedOutputStream(client.getOutputStream());
            xmlout.output(doc,outstream);
            outstream.flush();
            outstream.close();
            
            System.out.println("Eerste xml verzonden, bezig met verzenden van tweede...");
            
            outstream=new BufferedOutputStream(client.getOutputStream());
            xmlout.output(doc,outstream);
            outstream.flush();
            outstream.close();
De error krijg ik dus in Client:11 en Server:16.

Ik doe vast iets elementairs fout... het stomme is dat alle voorbeelden die ik ben tegengekomen altijd maar 1 ding versturen en dan weer afsluiten, tenzij ze een objectoutputstream gebruiken... maar dat wil ik niet aangezien ik schone XML wil spreken.

Ik heb de code ingekort om het overzicht te bewaren

[ Voor 1% gewijzigd door b19a op 19-04-2005 22:40 . Reden: typotjes ]


  • The Fox NL
  • Registratie: Oktober 2004
  • Laatst online: 06-05 23:46
Dat komt omdat je de Socket sluit nadat je het eerste bestand hebt verzonden (outstream.close() ).
Als je de connectie open wilt houden zul je die outstream.close() bij de client en reader.close() bij de server niet moeten aanroepen na ontvangst van het eerste bestand maar enkel wanneer je de connectie wilt sluiten.

  • b19a
  • Registratie: September 2002
  • Niet online
The Fox NL schreef op dinsdag 19 april 2005 @ 22:56:
Dat komt omdat je de Socket sluit nadat je het eerste bestand hebt verzonden (outstream.close() ).
Als je de connectie open wilt houden zul je die outstream.close() bij de client en reader.close() bij de server niet moeten aanroepen na ontvangst van het eerste bestand maar enkel wanneer je de connectie wilt sluiten.
Ja dat dacht ik in eerste instantie dus ook... ik laat dus in Server regel 12 en 16 weg, en in Client regel 8 en 12. Als ik dan de code uitvoer stopt de Server met deze dikke error:
Java:
1
2
3
org.jdom.input.JDOMParseException: Error on line 27: The processing instruction target matching "[xX][mM][lL]" is not allowed.
    at org.jdom.input.SAXBuilder.build(SAXBuilder.java:468)
    at org.jdom.input.SAXBuilder.build(SAXBuilder.java:770)
klik voor een langere foutcode*

Het lijkt me dus dat de SAXBuilder het niet leuk vindt om meerdere XML files te lezen en die zal op de een of andere manier een stopcode moeten krijgen!?!


* mocht de server het weer doen :O

  • The Fox NL
  • Registratie: Oktober 2004
  • Laatst online: 06-05 23:46
Je zegt in de topic titel dat je meerdere plain XML wil versturen, dus ik neem aan dat je gewoon tekst over en weer verzend. Misschien dat je het zo kunt oplossen door je XML bestanden als tekst te verzenden en zelf een soort van stopcode te verzinnen. Dan verstuur je de tekst en als je de stopcode ontvangt dan zet je gooi je de tekst van voor de stopcode in je SAXBuilder. (ff simpel gezegd)

  • b19a
  • Registratie: September 2002
  • Niet online
1. String parsing probleem: * opgelost
Ik heb dit geprobeerd maar de SAXBuilder wil geen strings lezen, ik zal deze string dus in een file moeten verpakken; een document; een inputreader; een inputsource; een character stream of een URL.

Ik heb geprobeerd een ByteArrayInputStream te maken en deze vervolgens naar de parser te sturen, maar ook deze komt met errors:
Java:
1
2
3
doc = builder.build(new java.io.BufferedInputStream(new java.io.ByteArrayInputStream(in.getBytes())));
// en deze werkt ook niet:
doc = builder.build(new java.io.ByteArrayInputStream(in.getBytes()));

edit:
Mijn conclusie was onterecht, de ByteArrayInputStream werkt wel correct, alleen een lege string erheen sturen (of andere foutieve inzending) liet het crashen...
Mijn vraag over punt 2 is dus nog niet opgelost/beantwoordt.



2. Einde xml probleem:
Ik gebruik nu dus "END_OF_XML;" als stopcode, maar wat nu als deze tekst in het XML-bestand zelf voorkomt? Zoals:
code:
1
2
3
                <param name="name" method="is">Bouke
END_OF_XML;
blaat</param>

Dan leest mijn Server dus het einde van het XML bestand en daarna begint hij ergens middenin een document te lezen. Hoe voorkom je zoiets? Is het dan misschien handiger om een code al "<end_of_xml />" te gebruiken en alle (<|>) die gebruikt worden binnen het XML-bestand te escapen naar &#; waarden?

[ Voor 121% gewijzigd door b19a op 20-04-2005 12:56 . Reden: gedachtenkronkel toegevoegd ]


  • The Fox NL
  • Registratie: Oktober 2004
  • Laatst online: 06-05 23:46
Om van een String een inputsource te maken kun je StringReader gebruiken:
InputSource input = new InputSource(new StringReader(hiermijnstring));

En van die stopcode, je kunt waarschijnlijk 2 dingen doen:
1) je verzint een stopcode waarvan je weet dat hij nooit zal voorkomen, maar zeker weten doe je dat natuurlijk nooit. De oplossing die jij aandraagt zal wel lukken denk ik.

2) Of je houdt bij wanneer de rootnode (de node waartussen al het andere xml staat) wordt gesloten. Als de rootnode <ikbenroot> is moet je de inkomende data bijhouden totdat je </ikbenroot> tegenkomt. En als die node meerdere keren voorkomt kun je met een simpel tellertje wel bijhouden wanneer je de sluitende node hebt gehad. Dus steeds als <ikbenroot> voorbij komt teller ophogen, als </ikbenroot> voorbij komt de teller verlagen. Als je bij nul begint kom je aan het einde weer bij nul uit en weet je dus dat je een xml file binnen hebt.

Succes verder

[ Voor 3% gewijzigd door The Fox NL op 20-04-2005 12:59 . Reden: spelfout ]


  • b19a
  • Registratie: September 2002
  • Niet online
Hartelijk dank! Alles begint zo al wat te werken :).

de klasse InputSource bestaat echter niet, maar door deze te vervangen met BufferedInputStream werkt alles prima! Nogmaals mijn dank :).

Voor die stopcode ga ik vooralsnog methode 1 toepassen (<end_of_xml/>), misschien in de toekomst iets robuuster maar dit zal vooralsnog volstaan!
Pagina: 1