/* ** This file is part of Filius, a network construction and simulation software. ** ** Originally created at the University of Siegen, Institute "Didactics of ** Informatics and E-Learning" by a students' project group: ** members (2006-2007): ** André Asschoff, Johannes Bade, Carsten Dittich, Thomas Gerding, ** Nadja Haßler, Ernst Johannes Klebert, Michell Weyer ** supervisors: ** Stefan Freischlad (maintainer until 2009), Peer Stechert ** Project is maintained since 2010 by Christian Eibl ** and Stefan Freischlad ** Filius is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 2 of the License, or ** (at your option) version 3. ** ** Filius is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ** PURPOSE. See the GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with Filius. If not, see . */ package filius.software.clientserver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import filius.rahmenprogramm.I18n; import filius.software.transportschicht.TCPSocket; /** *

* In dieser Klasse wird das Client-Programm einer einfachen Client-Server-Anwendung implementiert. Nachrichten an die * graphische Benutzungsoberflaeche werden durch den Aufruf banachrichtigeBeobachter(Object) versendet. *

*

* Aufrufe folgender Methoden des Sockets blockieren: *

* *

* Deshalb muessen Methoden dieser Klasse, die Aufrufe dieser Methoden enthalten, ueber die Methode * ausfuehren(String, Object[]) aufgerufen werden. Das bewirkt, dass diese Methoden in einem eigenen Thread * ausgefuehrt werden und damit der aufrufende Thread nicht blockiert. Das ist wichtig, wenn die Aufrufe von der * graphischen Benutzungsoberflaeche ausgeloest werden. *

*

* Ein Beispiel fuer die Verwendung von ausfuehren() ist folgendes:
* public void verbinden(String zielAdresse, Integer port) {
*    Object[] args;

*    args = new Object[2];
*    args[0] = zielAdresse;
*    args[1] = port;

*    ausfuehren("initialisiereSocket", args);
* } *

*

* Dabei wird als erstes Argument der auszufuehrenden blockierenden Methode * uebergeben (hier: initialisiereSocket) und dann in einem Array die zu uebergebenden Parameter (hier: * zielAdresse und port). Der Aufruf der Methode verbinden(zielAdresse, port) * bewirkt also das Ausfuehren der Methode initialisiereSocket(zielAdresse, port) in einem anderen * Thread. Damit blockiert die Methode verbinden nicht. *

*

* Achtung: Die indirekt aufgerufene Methode (d. h. ueber * ausfuehren(String, Object[])) muss als public deklariert sein! *

*/ public class ClientBaustein extends ClientAnwendung implements I18n { private static Logger LOG = LoggerFactory.getLogger(ClientBaustein.class); /** Port-Nummer des Servers, an dem Verbindungsanfragen angenommen werden */ private int zielPort = 55555; /** * Adresse des Rechners, auf dem der Server laeuft als Domainname oder IP-Adresse. */ private String zielIPAdresse; /** * Methode zum Verbindungsaufbau zu einem Server. Hier wird der Client-Socket als TCP/IP-Socket erzeugt. Wenn UDP * verwendet werden soll, muss diese Methode ueberschrieben werden.
* Diese Methode ist nicht blockierend. Diese Methode veranlasst den Aufruf von * initialisiereSocket in einem anderen Thread. */ public void verbinden() { LOG.trace("INVOKED (" + this.hashCode() + ", T" + this.getId() + ") " + getClass() + " (ClientBaustein), verbinden()"); Object[] args; args = new Object[2]; args[0] = zielIPAdresse; args[1] = Integer.valueOf(zielPort); ausfuehren("initialisiereSocket", args); ausfuehren("empfangeNachricht", null); } /** * Methode zum Aufbau einer Verbindung mit einem TCP-Socket. Diese Methode ist blockierend. */ public synchronized void initialisiereSocket(String zielAdresse, Integer port) { LOG.trace("INVOKED (" + this.hashCode() + ", T" + this.getId() + ") " + getClass() + " (ClientBaustein), initialisiereSocket(" + zielAdresse + "," + port + ")"); if (!istVerbunden()) { try { socket = new TCPSocket(getSystemSoftware(), zielAdresse, port); socket.verbinden(); benachrichtigeBeobachter(messages.getString("sw_clientbaustein_msg2")); } catch (Exception e) { LOG.debug("", e); socket = null; benachrichtigeBeobachter(messages.getString("sw_clientbaustein_msg1") + e.getMessage()); } } } /** * Methode zum trennen einer Verbindung. Der Socket wird durch den Aufruf der Methode schliessen() geschlossen und * und der Socket fuer diese Anwendung auf null gesetzt.
* Diese Methode ist blockierend. */ public void trennen() { LOG.trace("INVOKED (" + this.hashCode() + ", T" + this.getId() + ") " + getClass() + " (ClientBaustein), trennen()"); if (socket != null) { socket.schliessen(); socket = null; benachrichtigeBeobachter(messages.getString("sw_clientbaustein_msg3")); } } /** * Diese Methode blockiert bis die Nachricht versand wurde. Der Empfang der Antwort erfolgt asynchron. */ public void senden(String nachricht) { LOG.trace("INVOKED (" + this.hashCode() + ", T" + this.getId() + ") " + getClass() + " (ClientBaustein), versendeNachricht(" + nachricht + ")"); if (socket != null && socket.istVerbunden()) { try { socket.senden(nachricht); benachrichtigeBeobachter("<<" + nachricht); } catch (Exception e) { benachrichtigeBeobachter(e.getMessage()); LOG.debug("", e); } } else { benachrichtigeBeobachter(messages.getString("sw_clientbaustein_msg4")); } } /** * Methode zum Empfang einer Nachricht vom Socket. Die empfangene Nachricht wird mit * benachrichtigeBeobachter an die GUI weiter gegeben. Diese Methode ist blockierend und sollte nicht * direkt von der GUI aufgerufen werden. */ public void empfangeNachricht() { LOG.trace("INVOKED (" + this.hashCode() + ", T" + this.getId() + ") " + getClass() + " (ClientBaustein), empfangeNachricht()"); String nachricht; while (socket != null && socket.istVerbunden()) { try { nachricht = socket.empfangen(Long.MAX_VALUE); if (nachricht != null) { benachrichtigeBeobachter(">>" + nachricht); } else { socket.schliessen(); benachrichtigeBeobachter( messages.getString("sw_clientbaustein_msg5") + " " + socket.holeZielIPAdresse() + ":" + socket.holeZielPort() + " " + messages.getString("sw_clientbaustein_msg6")); } } catch (Exception e) { benachrichtigeBeobachter(e.getMessage()); LOG.debug("", e); } } } /** Methode fuer den Zugriff auf die Server-Adresse */ public String getZielIPAdresse() { return zielIPAdresse; } /** Methode fuer den Zugriff auf die Server-Adresse */ public void setZielIPAdresse(String zielIPAdresse) { this.zielIPAdresse = zielIPAdresse; } /** * Methode fuer den Zugriff auf die Port-Nummer, an dem der Server zu erreichen ist. */ public int getZielPort() { return zielPort; } /** * Methode fuer den Zugriff auf die Port-Nummer, an dem der Server zu erreichen ist. */ public void setZielPort(int zielPort) { this.zielPort = zielPort; } }