// ChatAsiakas25-26.java SJ // Ottaa yhteyden ChatPalvelimeen import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner; public class ChatAsiakas_pohja { private static String tunnus = "tunnus"; private PrintWriter out; private BufferedReader in; private Socket sock = null; private Thread pSaie = null; // palvelinta kuunteleva säie private Thread kSaie = null; // käyttäjää kuunteleva säie (pääsäie) private static boolean lopeta = false; // säikeet lopettavat toimintansa kun havaitsevat tämän olevan tosi public static void main(String[] args) { // oletusarvot String palvelimenOsoite = "localhost"; int portti = 11217; if (args.length > 0) { palvelimenOsoite = args[0]; } if (args.length > 1) { portti = Integer.valueOf(args[1]); } if (args.length > 2) { tunnus = args[2]; } ChatAsiakas_pohja a = new ChatAsiakas_pohja(); boolean stat = a.otaYhteys(palvelimenOsoite, portti); } // main() /** * Käsketään kaikkia säikeitä lopettamaan. */ private void lopetaKaikki() { lopeta = true; // herätetään odottava säie, suorituksessa olevalle ei tapahdu mitään kSaie.interrupt(); pSaie.interrupt(); } // yhteydenotto ja keskustelun kutsuminen private boolean otaYhteys(String osoite, int portti) { // talteen viite pääsäikeeseen kSaie = Thread.currentThread(); // yhteydenotto try { sock = new Socket(osoite, portti); // yhteydenotto System.out.println("Yhteys onnistui"); } catch (Exception e) { // yhteys ei varmaankaan onnistunut System.err.println("" + e); return false; } try { // luodaan keskustelukanavat out = new PrintWriter(sock.getOutputStream(), true); in = new BufferedReader(new InputStreamReader(sock.getInputStream())); // TODO // lähetä liittymisviesti // vastaanota kuittaus // perusta säie kuuntelemaan palvelimen lähettämiä viestejä // lue käyttäjältä viestejä ja lähetä palvelimelle sock.close(); // poikkeusten k?sittely } catch (Exception e) { System.err.println("" + e); return false; } // catch return true; } // otaYhteys() /** * Liittyminen kun yhteys on jo otettu. * @return null jos kaikke meni hyvin, virheilmoituksen merkkijonona muuten. */ String liity() { try { // TODO // lähetä liittymisviesti // vastaanota kuittaus return null; } catch (Exception e) { System.err.println("liity Poikkeus " + e); return "Poikkeus"; } } /** * Keskustelu käyttäjän kanssa. */ void juttele() { System.out.println("Anna viestejä, pelkkä piste rivillä lopettaa ja lähettää viestin."); System.out.println("LOPETA viestiksi lopettaa"); BufferedReader kayttaja = new BufferedReader( new InputStreamReader(System.in)); // luetaan viestiä tähän StringBuilder sb = new StringBuilder(); while (true) { sb.setLength(0); // tyhjennetään vanhat lueViesti(kayttaja, sb); // viesti käyttäjältä if ("LOP".equalsIgnoreCase(sb.substring(0, 3))) { lopetaOhjelma(); return; } // TODO // lähetä palvelimelle oikeassa muodossa } // while } // juttele() /** * Lopetetaan kun käyttäjä haluaa lopettaa */ void lopetaOhjelma() { try { lopeta = true; out.print(ChatProto.poistu + ChatProto.EOL); out.flush(); // kuittauksen lukee toinen säie lopetaKaikki(); sock.close(); } catch (IOException e) { e.printStackTrace(); } } /** * Viestin rungon lukeminen. * @param sb merkkipuskuri johon viesti lisätään. * @param in kanava jota luetaan. * @return null jos viesti on ok, muuten virheilmoituksen merkkijonona. **/ private String lueViesti(BufferedReader in, StringBuilder sb) { while (true) { try { String rivi = in.readLine(); if (rivi == null) return "Kanava loppui"; rivi = rivi.trim(); if (rivi.equals(ChatProto.EOM)) { // viestin loppu return null; // kaikki hyvin, EOM:ää ei laiteta viestiin tässä } else { sb.append(rivi); sb.append(ChatProto.EOL); } } catch (IOException e) { System.err.println("lueViesti poikkeus: " + e); return "Poikkeus luvussa"; } } // while } /** * Säie joka lukee palvelimelta viestejä. */ public class PalvelinLukija extends Thread { BufferedReader in; PalvelinLukija(BufferedReader i) { in = i; this.start(); } /** * Säikeen elämä. */ public void run() { // käytetään StringBuilderia ylläpitämään vastaanotettua viestiä StringBuilder sb = new StringBuilder(); try { while (! lopeta) { // TODO // luetaan otsikko, toimitaan sen mukaisesti String otsikko = in.readLine(); // TODO } } catch (Exception e) { if (! lopeta) System.err.println(e); } } /** * Tulostaa palvelimelta saadun viestin siten, että joka rivin alussa on tunnus. * @param sb viesti. * @param tunnus tunnus joka tulostetaan joka rivin alkuun. */ public void tulostaViesti(StringBuilder sb, String tunnus) { Scanner sc = new Scanner(sb.toString()); while (sc.hasNextLine()) System.out.println(tunnus + "> " + sc.nextLine()); } } // class PalvelinLukija }