Files
1ereNSI/reseau/filius/filius-1.12.5/tmpl/quelltext_vorlagen/client.txt

213 lines
8.7 KiB
Plaintext
Raw Normal View History

2022-05-04 18:39:31 +02:00
/*
** 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 <filius@c.fameibl.de>
** 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 <http://www.gnu.org/licenses/>.
*/
package filius.software.clientserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import filius.rahmenprogramm.I18n;
import filius.software.transportschicht.TCPSocket;
/**
* <p>
* 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.
* </p>
* <p>
* Aufrufe folgender Methoden des Sockets blockieren:
* </p>
* <ul>
* <li>verbinden()</li>
* <li>senden()</li>
* <li>empfangen()</li>
* <li>schliessen()</li>
* </ul>
* <p>
* Deshalb muessen Methoden dieser Klasse, die Aufrufe dieser Methoden enthalten, ueber die Methode
* <code>ausfuehren(String, Object[])</code> 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.
* </p>
* <p>
* Ein Beispiel fuer die Verwendung von <code>ausfuehren()</code> ist folgendes: <br />
* <code> public void verbinden(String zielAdresse, Integer port) { <br />
* &nbsp;&nbsp; Object[] args; <br /> <br />
* &nbsp;&nbsp; args = new Object[2]; <br />
* &nbsp;&nbsp; args[0] = zielAdresse; <br />
* &nbsp;&nbsp; args[1] = port; <br /> <br />
* &nbsp;&nbsp; ausfuehren("initialisiereSocket", args); <br />
* }
* </p>
* <p>
* Dabei wird als erstes Argument der auszufuehrenden blockierenden Methode
* uebergeben (hier: <code> initialisiereSocket</code>) und dann in einem Array die zu uebergebenden Parameter (hier:
* <code>zielAdresse</code> und <code>port</code>). Der Aufruf der Methode <code>verbinden(zielAdresse, port)
* </code> bewirkt also das Ausfuehren der Methode <code>initialisiereSocket(zielAdresse, port)</code> in einem anderen
* Thread. Damit blockiert die Methode <code>verbinden</code> nicht.
* </p>
* <p>
* <b> Achtung:</b> Die indirekt aufgerufene Methode (d. h. ueber <code>
* ausfuehren(String, Object[])</code>) muss als <code>public</code> deklariert sein!
* </p>
*/
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. <br />
* Diese Methode ist <b>nicht blockierend</b>. Diese Methode veranlasst den Aufruf von
* <code>initialisiereSocket</code> in einem anderen Thread.
*/
public void verbinden() {
LOG.debug("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.debug("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. <br />
* Diese Methode ist <b> blockierend</b>.
*/
public void trennen() {
LOG.debug("INVOKED (" + this.hashCode() + ", T" + this.getId() + ") " + getClass()
+ " (ClientBaustein), trennen()");
if (socket != null) {
socket.schliessen();
socket = null;
benachrichtigeBeobachter(messages.getString("sw_clientbaustein_msg3"));
}
}
/**
* Diese Methode <b>blockiert</b> bis die Nachricht versand wurde. Der Empfang der Antwort erfolgt asynchron.
*/
public void senden(String nachricht) {
LOG.debug("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
* <code>benachrichtigeBeobachter</code> an die GUI weiter gegeben. Diese Methode ist blockierend und sollte nicht
* direkt von der GUI aufgerufen werden.
*/
public void empfangeNachricht() {
LOG.debug("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;
}
}