_ 2.1.2 Stream sockets på serversidan Vi fortsätter med lågnivåkopplingar med stream sockets men nu på serversidan. __ Uppgift Gör ett program som implementerar en chattserver som kan sända och ta emot textmeddelanden. Chattservern ska använda stream sockets. Chattservern ska kunna ta emot begäran om uppkoppling från nya chattklienter och placera alla chattklienter i en egen tråd för att kunna ta emot ytterligare chattklienter. Varje chatklienttråd ska ligga och väntar på att en chattklient ska sända ett textmeddelande. När så sker så ska chattservern sända/broadcasta detta meddelande till samtliga chattklienter. Chattservern måste således hålla reda på alla anslutna chattklienter i någon datasamling. Alla textmeddelanden som sänds från chattklienterna ska visas för användaren. För samtliga textmeddelanden så ska följande skrivas ut: - Chattklientens IP-adress - Textmeddelandet från chattklienten Chattservern ska gå att starta på två sätt: = §java Server§ (då ska port default bli §2000§) = §java Server § Efter detta ska chattservern göra sig redo för att ta emot förfrågningar om anslutning från chattklienter. Om detta lyckas så ska det i chattserverns titelrad stå den host och port som chattservern kör på samt antalet chattklienter som är uppkopplade. Observera! Chattservern ska upptäcka när en klient inte längre är ansluten och då ta bort den ur datasamlingen och döda tråden (eventuellt kan tråden döda sig själv). __ Exempel Ett enkelt exempel kan köras enligt följande: = Hämta filen: §[Server.jar, 05_ass/ip1/2/2.1.2/Server.jar]§ = Kör programmet med: §java -jar Server.jar§ Detta startar chattservern på port §2000§ men man kan även ange ett annat portnummer som ett tredje argument, exempelvis §java -jar Server.jar 2001§. Ett enkelt exempel utan GUI kan köras enligt följande: = Hämta filen: §[Server.class, 05_ass/ip1/2/2.1.2/terminal_version/Server.class]§ = Kör programmet med: §java Server§ __ Tips Använd klassen §ServerSocket§ och metoden §accept§. Man måste vara försiktig med krockar. Man har ju ofta flera trådar igång för hantering av anslutna chattklienter och det kan exempelvis bli fel om man samtidigt: = Tar bort en chatklienttråd = Sänder/broadcastar ett meddelande För att lösa detta bör man deklarera vissa metoder i chattservern som §synchronized§. Hur upptäcker chattservern att en chattklient har kopplat ner? För varje chattklient som kopplar upp sig till chattservern så skapar chattservern en egen tråd för chattklienten. Antag att klassen som hanterar chattklienterna heter §ClientHandler§ och är en tråd som hela tiden ligger och lyssnar på om klienten har sänt något meddelande. Om ett meddelande kommer från en chattklient så anropar §ClientHandler§ en metod i chattservern som sänder/broadcastar meddelandet till alla anslutna chattklienter. Det är i denna lyssningsfas som §ClientHandler§ kan upptäcka om en klient har kopplat ner: = Om chattklienten beter sig korrekt och stänger sin utström returnerar läsning med (§BufferedReader§) §readLine§-metoden §null§. Klienten under uppgift [2.1.1 Stream sockets på klientsidan, 05_ass/ip1/2.1.1.txt] gör detta om man sänder §exit§ som meddelande. = Om chattklienten inte beter sig korrekt och inte stänger sin utström blir det §IOException§ vid läsning med (§BufferedReader§) §readLine§-metoden. Klienten under uppgift [2.1.1 Stream sockets på klientsidan, 05_ass/ip1/2.1.1.txt] gör detta om man stänger fönstret för klienten. Man får då undersöka dessa båda fall och om något av dem uppstår så ska man gå ut ur den "eviga" lyssnarloopen, exempelvis: § public void run() { String msg; try { while ((msg = reader.readLine()) != null) { //... gör något med msg ... } writer.close(); reader.close(); socket.close(); } catch (IOException e) { } server.killThread(this); } § Precis efter §try§-blocket ligger satserna som stänger alla strömmar, och eftersom de genererar §IOException§ kan de ju lika gärna ligga i §try§-blocket. Om ett §IOException§ har inträffat tidigare kan man ju antagligen inte stänga strömmarna i alla fall. Exempel på lämpliga strömkopplingar till klientsocketen: § in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); out = new PrintWriter(clientSocket.getOutputStream(), true); § Hur får man reda på server-socketens hostadress: § String host = serverSocket.getInetAddress().getLocalHost().getHostName(); § Hur får man reda på klientsocketens hostadress: § String host = socket.getInetAddress().getHostName(); § Som överkurs kan man titta på paketet §java.nio§, exempelvis på klassen §ServerSocketChannel§. __ Hjälp ~ 05_ass/help/01.txt > [Klicka här för hjälp, helper.dsv@gmail.com, Prog Internet: 2.1.2 Stream sockets på serversidan: http://people.dsv.su.se/~pierre/i/i.cgi?href=05_ass/ip1/2.1.2.txt] ½===system_tutoring_message===½ < ~ 05_ass/help/02.txt