28. marts 2003 - 21:58Der er
80 kommentarer og 1 løsning
Kommunikation mellem tråde, socket lukkes
Hejsa,
Er i færd med at lave en nameserver og en fileserver. Førstnævnte håndterer en række klienter og ekspederer deres filrequest videre til fileserveren.
Nameserveren fungerer således; Klassen består af 2 innerclasses; ClientThread og FileServerThread, når en klient logger på oprettes en tråd af ClientThread som styrer kommunikationen mellem klient og server ved hjælp af BufferedReader og OutputStream. Når klienten beder om en fil opretter ClientThread et objekt/tråd af FileServerThread (alt sammen foregår i nameserver-klassen), denne tråd virker som klient i forhold til fileserveren og kommunikerer ligesom klienten gør med nameserveren. PUHA... det gælder om at holde tungen lige i munden...
Hvor om alting er så virker ovenstående fint således; klienten sender besked til ClientThread i nameserver, denne sender beskeden videre (gennem FileServerThread) til fileserveren som kan læse beskeden (og skrive den ud i sin egen terminal) og sende den retur til FileServerThread i nameserver! (men her knækker filmen så)...
Sagen er, at i nameserver-klassen skal FileServerThread sende beskeden til ClientThread for at denne kan sende via den oprettede socket til klienten (altså kommunikation mellem de to innerclasses/tråde), hvordan fikses den lige??? Jeg har prøvet af parameteroverfører det clientThread-objekt som opretter FileServerThread (således den har en anelse om hvorfra beskeden oprindeligt kom) - hvilket ikke løser problemet. Beskeden skal jo tilbage til klienten og ikke bare huserer i nameserveren.
Den fejl jeg får er; java.net.SocketException: Socket closed at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:99) at java.net.SocketOutputStream.write(SocketOutputStream.java:124) at Nameserver.writeLine(Nameserver.java:245) at Nameserver.access$400(Nameserver.java:5) at Nameserver$ClientThread.responce(Nameserver.java:146) at Nameserver$FileServerThread.run(Nameserver.java:193) at java.lang.Thread.run(Thread.java:536)
Noget i retning af: * NameServerMain som lytter på ServerSocket creater ClientThread's * ClientThread som creater ClientConnection og processer requests fra client * ClientConnection som indeholder Socket * FileServerConnection som indeholder Socket
Når der kommer en request fra client om en fil så åbner ClientThread en FileServerConnection, beder om filen, får filen og sender den tilbage via ClientConnection.
Hmm... ok... Min tråd-teknik er sikkert noget underlig og hvis du gider vil jeg gerne lære en smartere måde at arbejde med tråde på... Kan ikke just prale af, at min kodning foregår struktureret :-)
Hvad er der galt med JDK 1.4.x? Eneste der skal laves om i koden for at den virker til tidligere versioner er min en- og decoding hvor formattet i 1.4.x skal med hver gang.
hmm... ok... så du opretter altså Thread objektet udenfor den klasse som 'implements Runnable'? I mit tilfælde betyder det, at jeg skal lave tråd-objektet i nameserver?
Hvordan er du blevet så klog? Bliver tilstadighed overrasket over den viden du sidder inde med, ikke bare i java men også i alle de andre ting du ved noget om... Du er vel - uden det skal lyde klamt - mit yndlings orakel :O)
bruger normalt JBuilder, men i dette tilfælde lavede jeg al koden i hånden i TextPad, da jeg sad ved en puter uden JBuilder... Jeg syntes heller ikke JBuilder egner sig særligt godt hvis man slam-koder... Jeg bruger mest JBuilder fordi jeg er helt tosset med pop-up API'et, det er sku en fræk detalje!
By the way, hvis nu mit lille program her skal virke rigtigt, så skal fileserveren jo sende en fil og ikke en streng (det er for kedeligt). På den måde bliver jeg vel nødt til at oprette 2 strømme mellem nameserver og fileserver, da jeg først skal fortælle fileserveren hvilken fil jeg vil have og siden have den sendt... By the way, så skal den jo helt tilbage til klienten, er det ikke muligt at holde nameserveren udenfor al returkommunikationen?? Det belaster bare den unødigt!
Bla bla bla, nu er jeg blevet varm, så der kommer lige et questiones mere;
hvordan kan jeg designe nameserveren således den med et givent interval opdaterer sit register med filer på fileserveren? hvis nu vi havde 2 eller flere fileservere der løbende ændrer sig, har vi jo brug for at holde nameserveren opdateret...
hmm... lyder nemmere sagt end gjort, har mildest talt ikke de store erfaringer med bytes og konventioner som du taler om... findes der eksempler nogen steder på nettet?
Jeg er med på, at jeg kan skrive og sende til samme socket, det var mere selve strømmen jeg tænkte på, eksempelvis BufferedReader osv.
ja, det er vist rigtigt nok, den arkitektur der er pt. er vist meget god... Problemet med den er jo bare at nameserver bliver en flaskehals, men det findes der vel teknikker for at undgå... (flere nameservere måske)
ok, tror jeg går efter Timer eksemplet, har noget kode i forvejen der virker genialt til lige netop det formål, hvordan skal jeg gøre det i praksis? Lave en særlig tråd der med sin egen socket arbejder med opdatering eller huh?
Timer klassen starter din klasse (som implementerer TimerTask) i en separat tråd, så du skal bare lave en helt normal klasse, så laver Java tråden for dig.
På Nameserver siden.
På FileServer siden er det vel bare en halvnormal form for connection.
hø hø, halvnormal... den er vist for advancerede programmørere... jeg er lidt i tvivl :-) en helt normal klasse bruger vel stadig en socket til at kommunikere med fileserveren?
ahh... haaar det... jeg tænkte jo straks på at jeg skulle have mig en rigtig lille husbestyrerinde-proces der støvede arkiverne af... men det sørger timer-klassen for, hvilket gør det lidt nemmere. Men fra fileserverens synspkt, kommer der altså to slags klienter på besøg; timer-klassen som holder nameserveren 'up 2 date' og endeligt de deciderede filerequest
by the way... sætter stor pris på at du gider tage dig tid til det her!!! Det jeg savner mest her i livet (indenfor java-verden) er en kultur ligesom ovre hos php-folket. Tænker især på de mange gatherings og conferences, det ville være great hvis vi her i Danevang eller bare i Københavns-området have en slags 'nørder mødes og udveksler viden og ellers hygger sig'-agtig kultur... Bare en strøg tanke
ahh... syntes jeg har fået en del AHA-oplevelser ud af vores lille 'chat'... Skriver du ikke en bog :-) I'll be the first bying it :-)
Så det bliver (i dette tilfælde) FileServerThreads opgave at tildele tråden en socket! Det er egentligt også det der var tanken sådan som koden er nu, men den opretter jo kommunikationen på samme socket... Skal jeg lave et random socket nummer eller hvordan sikrer jeg mig at hver tråd får sin egne socket?
Med hensyn til Java versus PHP, så tror jeg at Java folkene gennemgående er lidt ældre og hyppigere har faste jobs og de er nok mere til internet fora'er end get-together's.
Men Java kategorien her på eksperten er ret aktiv.
Hvis vi går uden for landets grænser (og kikker på Java på server) så er der TSS.
har også det indtryk... det virker heller ikke som om jsp og servlet er slået helt vildt igennem... det er skide dyrt at få hostet og der er ikke særligt mange udbydere... Lidt en skam at man ikke kan bruge det man har lært i java på nettet, men er nødsaget til at scripte gennem asp, php (i nogen tilfælde jsp, men ikke særligt udbredt alligevel)...
JSP/servlet er ikke særligt udbredt til rene "vis" løsninger og er derfor ikke særligt udbredt på web-hoteller som typisk får "vis" løsninger.
JSP/servlet er særdeles udbredt (som frontend) til "transaktions" løsninger. Men sådanne skal jo i sagens natur hostes hjemme i firmaet fordi de skal forbindes med resten af firmaets IT systemer.
klart... men til at øve sig ville det være rart med et host (der er til at betale) Nu vi er ved emnet, hvilken web-server anbefales hvis man vil lege lidt med jsp og servlets? Apache rygtes at være bedre end Tomcat, men jeg ved ærligt talt ikke meget om det - andet end jeg gerne vil prøve det lidt af...
ok, nu tror jeg, jeg fatter noget... problemet er, at jeg lader klienttråden i nameserveren bruge samme Socket-objekt, fremfår at de får hver deres objekt at lege med...
kender ikke til .net, men har hørt meget godt om det (selvom det er 'made in M$'land')
Jeg er af den overbevisning, at fatter man bare en smule java, klasser, polymorfi, rekursion osv... så kan man lave nogle interessante løsninger i jsp/servlet. PHP har jo nærmest udviklet sig i samme retning hvad angår klasser, objekter o. lign.
Den gennemsnitlige hjemme-side programmør mener at Java er noget man laver applets i, han har hørt om klasser og tror at polymorfi må være en lokal skik i polynesien.
Tusinder tak for din hjælp i dag, det var lige hvad jeg manglede... nu håber jeg bare jeg kan få skidtet til at du! Hvis du finder noget grelt på et senere tidspunkt må du meget gerne poste det :-)
det tror jeg på, det kan bare være lidt svært at holde overblikket i programmet, men så er det godt at du er til :-)
For lige at summere op; Klient.java forbliver uændret NameServer.java ændres således; FileServerThread-innerklassen fjernes ClientThread-klassen (CT) laves outer og der oprettes en tråd af denne i nameserver-klassen når en klient logger på. CT sørger for at lave en connection til FileServer (behøves ikke være en tråd) -- kommer lidt i tvivl her... kan jeg være sikker på, at når nameserver opretter en CT, så bliver det socket objekt der oprette i CT ikke delt mellem de forskellige CT's? (min pointe er, at den kode der skal laves i CT, blot skal oprette et socket-objekt uden at tænke på at den er en del af et større multi-threading program?) Jeg forudsætter at der ikke opstår socket-problemer...
Som verden så ser ud, så har jeg problemer med at lade CT-tråden svarer den oprindelige klient, hvordan ved denne tråd hvilken klient der i sin tid connectede nameservere???
Nameserver laber: Socket sock = servsock.accept(); (new ClientThread(sock)).start(); så får hver ClientThread sin egen Socket.
ClientThread opretter så en Socket til FileServer. Den Socket kan bare være en lokal variabel inde i en metode. connect/x reads/close. Det den læser skriver den tilbage til Socket objektet den gemte i sin constructor (og som har forbindelsen til klienten).
lige præcis det jeg har haft problemer med... ALtså at skrive tilbage til klienten. Jeg fik fejlen (socket closed) men jeg må lige sove på det, ændre koden som du har sagt og se om ikke der sker noget :-)
Så er jeg lidt i tvivl om hvordan fileserver kender forskel på hvem der connecter til den. Sagen er jo, at de mange tråde i Nameserveren opretter forbindelse til Fileserveren mhp. udlevering af en given fil. Derudover findes der én connection fra nameserver til fileserver som timeren styrer, der hele tiden (eller i et vist interval) spørger Fileserveren om sit indhold. (det er dog ikke kodet endnu).
Hvordan håndteres det i Fileserveren?
Derudover; et spørgsmål ang. trådene. Hvordan holder Nameserveren styr på de tråde den starter? Findes der en måde hvorpå trådene kan dele information, det kunne eksempelvis være listen over fileserverens indhold. Kan en tråd fortælle nameserveren (som jo oprettede den) at den er færdig og dræbt?
ok, den er jeg med på, men hvad nu hvis trådene i nameserver skal bruge den liste som en helt anden tråd i nameserver (timer-fidusen) laver? Skal listen så overføres på linje med socket?
Jeg kunne også godt tænke mig at vide om en tråd fra nameserver havde mulighed for at 'notify' nameserver når den var færdig... Altså lidt ligesom i C, hvor en proces har en parent?
Der er flere muligheder for at markere at Thread er done. En meget simpel er at have en isDone metod ei thread klassen og lade main thread have en referance til objektet og teste via isDoen metoden.
Ang. 19:11:49, går ud fra at du mener, at fileserverens run-metode skal være så generisk at den både kan håndterer liste-opdaterings-forespørgsler og filerequests? Jeg er lidt i tvivl om hvordan den fikses! Når timeren sætter ind skal den have en streng eller en eller anden form for liste retur indeholdende en opdateret filliste. Men når ClientConnectionNameserver kommer på banen, hvilket vel er det der sker 9 ud af 10 gange, skal der sendes noget helt andet retur... Svært at gøre generisk...
Det ville være federe hvis fileserveren havde mulighed for at skelne.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.