import java.net.ServerSocket; import java.net.Socket; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.PrintWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; /** En ClientThread är en tråd som tar emot meddelanden från en klient. * Varje uppkopplad klient har ett eget ClientThread-objekt. * @author Thomas Padron-McCarthy * @version 2.0 */ public class ClientThread extends Thread { /** Antalet skapade ClientThread-instanser. * Variabeln räknas inte ner när ett objekt försvinner, * och den räknar alltså antalet skapade instanser, * inte det anatl som just nu existerar. */ private static int numberOfClients = 0; /** En lista över alla just nu existerande ClientThread-instanser. */ private static ArrayList allClients = new ArrayList(); /** Ett unikt ordningsnummer på denna ClientThread-instans, * och på den uppkopplade klienten. * Ordningsnumren börjar på 1, och ökas med 1. */ public final int clientNumber = ++numberOfClients; private final Socket socket; private final BufferedReader in; private final PrintWriter out; /** Ett unikt ordningsnummer på denna ClientThread-instans, * och på den uppkopplade klienten. * Ordningsnumren börjar på 1, och ökas med 1. * @param s en nyligen skapad, öppen socket som är kopplad till en klient * @throws IOException om det inte går att koppla läs- * och skriv-strömmar till socketen s. * Om konstruktorn kastar IOException, * kommer den inte att stänga socketen s, * utan det är den anropande metodens ansvar. * Om konstruktorn lyckas, * tar ClientThread-instansen över ansvaret för att så småningom stänga socketen s. */ public ClientThread(Socket s) throws IOException { socket = s; in = new BufferedReader( new InputStreamReader( socket.getInputStream())); out = new PrintWriter( new BufferedWriter( new OutputStreamWriter( socket.getOutputStream())), true); // true: PrintWriter is line buffered System.out.println("Klienttråd " + clientNumber + " skapad."); out.println("Välkommen. Du är klient nummer " + clientNumber + "."); allClients.add(this); // If any of the above calls throw an // exception, the caller is responsible for // closing the socket. Otherwise the thread // will close it. start(); // Starts the thread, and calls run() } /** Anropas av Java-maskinen när tråden startas. */ public void run() { try { while (true) { String inline = in.readLine(); System.out.println("Klienttråd " + clientNumber + " tog emot: " + inline); // Not: inline == "quit" if (inline == null || inline.equals("quit")) break; out.println("Du sa '" + inline + "'"); Iterator i = allClients.iterator(); while (i.hasNext()) { ClientThread t = (ClientThread)i.next(); if (t != this) t.out.println("Från klient " + clientNumber + ": " + inline); } } System.out.println("Klienttråd " + clientNumber + ": Avslutar..."); } catch(IOException e) { System.out.println("Klienttråd " + clientNumber + ": I/O-fel"); } finally { try { socket.close(); } catch(IOException e) { System.out.println("Klienttråd " + clientNumber + ": Socketen ej stängd"); } allClients.remove(allClients.indexOf(this)); } } // run } // class ClientThread