Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
"Jungfernflug" der Socketprogrammierung für ein Mühlespiel
Anforderungen :
Die OnlineVariante des MühleSpiels soll in Form einer Client/ ServerArchitektur umgesetzt werden. Zu diesem Zweck soll ein Server implementiert werden, der auf Spielanfragen wartet. Melden sich zwei Spieler an, wird ein Spiel gestartet. Der Spielzustand soll zentral auf dem Server verwaltet werden.
Der Informationsaustausch zwischen den zwei Spielern und dem Server soll
über ein verbindungsorientiertes und sicheres Protokoll realisiert werden.
Greifen Sie zu diesem Zweck auf die im Paket java.net bereitgestellten
Klassen Socket ( = Client ) und ServerSocket ( = Server ) zurück.
Jeder Spieler soll zu jedem Zeitpunkt in der Lage sein, ein Spiel abzubrechen.
Der Gegenspieler soll über den Abbruch des Spiels informiert werden. Nach
Ende oder Abbruch eines Spiels soll ein neues Spiel gestartet werden können.
da hab ich gleich mal ne Frage...also ganz rustikal natürlich, wie immer *g*, ich muss einen Server programmieren, das steht in nem Buch( zumindest Ansatzweise)...die Frage ist gleich ...bei meiner Klasse Mühle, muss ich doch den Konstruktor ändern oder???, denn ich schicke ja dem, der mitspielen will ein Paket an Daten, mit nem zweiten Konstrukuor (dem ich nen Port und ne Internetadresse übergebe), spielt der andere Spieler und "wirft" alles wieder zu mir, ...hab da sowas in der Art gelesen ??? geht das in die richtige Richtung ???
nochmal so für mich: wir haben ja die Offlinevariante fertig, müssen die Klasse, im speziellen, dem Konstruktor wie oben beschrieben abändern und etwaige Ausnahmenbedingen hier und da einbauen und vielleicht noch ein paar Methoden in der Klasse Mühle ergänzen ... ist das so für den Anfang der richtige Weg oder laufen wir Gefahr in einer Sackgasse zu landen ???
wie wäre denn im worst case, der Fahrplan für einen Ausweg ???
alle bisherigen Klassen zum Spiel sollten weitgehend unverändert bleiben,
die Sockets müssen den Spielstand übertragen und höchstens noch anstelle der Spieler spielen,
wenn es also bisher etwa
Zug x = liesEingabeVonKonsoleFürSpieler1();
spiel.verarbeiteZug(x);
gab, dann lautet es nun
Zug x = liesEingabeVonSocketSpieler1();
spiel.verarbeiteZug(x);
für die Spiel-Klasse ändert sich also gar nix,
außer zur Übertragung muss es vielleicht Methoden a la
speichereSpielstandAlsString()
+
baueSpielstandAusStringAuf()
oder so geben,
vielleicht aber auch nicht mal das, wenn alle den Anfangsstand kennen + die Liste der getätigten Spielzüge,
dann weiß jeder wie es steht,
der Server muss natürlich prüfen, dass die Sockets erlaubte Züge liefern, aber das sollte im Einzelspiel bei den Eingaben auch passieren,
ebenso Sieg bestimmen usw., das müsste es alles geben bzw. ist recht unabhängig davon, ob das Spiel übers Netz läuft und von einem unabhängigen Server kontrolliert wird
Was bedeutet "sicher" hier? SSL? One time pad Verschlüsselung? ;-)
Zu deiner Frage: Ich habe keine Ahnung, wie dein Konstruktor aussieht und was du bisher gemacht hast. Unabhängig davon vermute ich aber, dass der Konstruktor dein geringstes Problem sein wird und der auch nicht angepasst werden muss. Versuch's einfach, dann siehst du ob der Konstruktor passt oder evtl. ein zweiter her muss.
ich muss mich auch erstma weiter in das Thema einlesen, was ich aber noch nicht verstehe wie das funzt... immer alles schon gesagt, irgendwas hier und da auf nem Server ablegen und listener und sonst was spielen...
direkt meine frage ist, wie man das selbst am rechner testet, dass das was man geproggt hat,auch funktioniert.
ich meine das so: (p.s. laut anforderungen kann man das testen mit localhost oder sowas, moment ich guck mal eben nach:
"Sie können ihre Umsetzung der OnlineVariante
des Spiels zunächst auf einem
Rechner testen, indem Sie das Loopback Network Interface dieses Rechners
nutzen ( localhost, IP4Adresse:
127.0.0.1 )" ...........
die wohl eigentlichen fragen kommen jetzt ( sorry bin schon völlig wirre *g*):
1. ich sitze vor meinem eclipse , starte das programm und muss es dann nochmal starten ??? dies implizert meine 2. frage
2. wenn ich anfange , bin ich dann gleichzeitig Server und Client ....also wie muss ich die Anforderungen s.o. interpretieren, ist es egal, sollte ich lieber nochmal nachfragen wie die das meinen oder wie oder was...
"Im zweiten Schritt soll das MühleSpiel
um eine OnlineVariante
erweitert werden.
Diese soll es zwei Spielern ermöglichen, das Spiel auch auf entfernten aber durch
ein Netzwerk miteinander verbundenen Rechnern zu spielen. Die Spieloberfläche soll
dabei wiederum durch eine graphische Benutzerschnittstelle implementiert werden,
die einzelne Spielzüge über die Maus empfängt."
verstehe ich nicht...oder besser ist es mir momentan fast egal ob das Mühlespiel nun auf einem Server liegt ....aja ich glaube langsam ... der andere Mitspieler am anderen Ende des Raumes an einem anderen PC , bekommt von mir ne Internetadresse, da kann er dann klicken und mitspielen egal ob ich nun gleichzeitig der server bin oder der server nun woanders ist....ach man, alles nicht so einfach, für mich zumindest....
ja die nächste frage wäre ja dann( wenn ich so halb recht hab), was wäre einfacher: ich gleichzeitig server und client oder den server irgendwohin ( wie auch immer..."noch") und mein gegenspieler und ich clienten
so, da bin ich mal wieder... ob nun schlauer als vorher, wird sich noch zeigen...
ich bin nun der meinung, das ich gleichzeitig server und client sein kann und woanders der client sitzt...
was ich nun brauche sind die klassen server und client, auch mit reichlichen beispielen, seh ich da noch kein land, was da wo wie hinkommt, ich brauche flush, close, accept, input, output... etc pp, das is aber erstma mein zweites problem ^^
das größere problem is die spielklasse umzuschreiben... ich dreh mich gerad im Kreis ob ich nun initialisieren oder den Konstrukor ändern muss...für weiteres folgen ersteinmal die originalen methoden
Java:
public Mühle() {
frame = new JFrame("Mühle");
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
System.exit(0);
}
});
brett = new Spielbrett(300, 300);
pool = new Steinpool(300, 100);
lPlayer = new JLabel("", 0);
lAktion = new JLabel("", 0);
menubar = new JMenuBar();
mSpiel = new JMenu("Spiel");
mOptionen = new JMenu("Optionen");
miNeu = new JMenuItem("Neues Spiel");
miExit = new JMenuItem("Spiel Beenden");
mSpiel.add(miNeu);
mSpiel.add(miExit);
menubar.add(mSpiel);
menubar.add(mOptionen);
miExit.addActionListener(this);
miNeu.addActionListener(this);
pnlMain = new JPanel(new BorderLayout());
pnlLinks = new JPanel(new BorderLayout());
pnlRechts = new JPanel(new GridLayout(0, 1));
brett.addMouseListener(this);
pnlLinks.add(brett, BorderLayout.NORTH);
pnlLinks.add(pool, BorderLayout.SOUTH);
pnlRechts.add(lPlayer);
pnlRechts.add(lAktion);
pnlMain.add(pnlLinks, BorderLayout.WEST);
pnlMain.add(pnlRechts, BorderLayout.EAST);
pnlRechts.setPreferredSize(new Dimension(200, 0));
frame.add(pnlMain);
frame.setJMenuBar(menubar);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
initialisieren();
}
public void initVerbindung(Socket socket)
{
try
{
ps = new PrintStream(socket.getOutputStream());
scan = new Scanner(socket.getInputStream());
}
catch (Exception e)
{
e.printStackTrace();
}
new Thread((Runnable) this).start();
}
so, müssten noch server und client her und alles wäre cool...achja initialisiere2 noch aufgerufen im konstruktor....und nebenbei denke ich mir, könnte es mit dem zufälligen anfang probleme geben, falls nicht, kommt der eben wieder rein
ABER, zwischenzeitlich dachte ich mir. da ja in der methode initialisieren alles rein kommt was man braucht um das spiel sauber starten zu können, kommt mir meine erste idee ein wenig komisch vor.. oder wie seht ihr das ???
ich sag nochmal, falls es noch niemanden aufgefallen sollte, wir sind keine javaprofis ^^
wiederum den konstruktor zu ändern, halte ich für schwachsinn...da ....ah warte mal...vielleicht muss ich doch nur den Konstrukor ändern der art wie ich initialisieren geändert habe und lasse die methode initialisieren so wie sie war...im konstrukor sind alle einmaligen sachen und initialisieren wird überall aufgerufen, könnte wiederrum ein problem mit dem zufallsanfang sein...quellcode kommt gleich....übrigens habe ich noch PrintStream ps;Scanner scan; vorher deklariert
Java:
PrintStream ps;
Scanner scan;
public Mühle() {
frame = new JFrame("Mühle");
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
System.exit(0);
}
});
brett = new Spielbrett(300, 300);
pool = new Steinpool(300, 100);
lPlayer = new JLabel("", 0);
lAktion = new JLabel("", 0);
menubar = new JMenuBar();
mSpiel = new JMenu("Spiel");
mOptionen = new JMenu("Optionen");
miNeu = new JMenuItem("Neues Spiel");
miExit = new JMenuItem("Spiel Beenden");
mSpiel.add(miNeu);
mSpiel.add(miExit);
menubar.add(mSpiel);
menubar.add(mOptionen);
miExit.addActionListener(this);
miNeu.addActionListener(this);
pnlMain = new JPanel(new BorderLayout());
pnlLinks = new JPanel(new BorderLayout());
pnlRechts = new JPanel(new GridLayout(0, 1));
brett.addMouseListener(this);
pnlLinks.add(brett, BorderLayout.NORTH);
pnlLinks.add(pool, BorderLayout.SOUTH);
pnlRechts.add(lPlayer);
pnlRechts.add(lAktion);
pnlMain.add(pnlLinks, BorderLayout.WEST);
pnlMain.add(pnlRechts, BorderLayout.EAST);
pnlRechts.setPreferredSize(new Dimension(200, 0));
frame.add(pnlMain);
frame.setJMenuBar(menubar);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
initialisieren();
try
{
ServerSocket server = new ServerSocket(0);
System.out.println("Port: " + server.getLocalPort());
initVerbindung(server.accept());
}
catch (Exception e)
{
e.printStackTrace();
}
}
public Mühle(String inetAddr, int port) {
frame = new JFrame("Mühle");
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
System.exit(0);
}
});
brett = new Spielbrett(300, 300);
pool = new Steinpool(300, 100);
lPlayer = new JLabel("", 0);
lAktion = new JLabel("", 0);
menubar = new JMenuBar();
mSpiel = new JMenu("Spiel");
mOptionen = new JMenu("Optionen");
miNeu = new JMenuItem("Neues Spiel");
miExit = new JMenuItem("Spiel Beenden");
mSpiel.add(miNeu);
mSpiel.add(miExit);
menubar.add(mSpiel);
menubar.add(mOptionen);
miExit.addActionListener(this);
miNeu.addActionListener(this);
pnlMain = new JPanel(new BorderLayout());
pnlLinks = new JPanel(new BorderLayout());
pnlRechts = new JPanel(new GridLayout(0, 1));
brett.addMouseListener(this);
pnlLinks.add(brett, BorderLayout.NORTH);
pnlLinks.add(pool, BorderLayout.SOUTH);
pnlRechts.add(lPlayer);
pnlRechts.add(lAktion);
pnlMain.add(pnlLinks, BorderLayout.WEST);
pnlMain.add(pnlRechts, BorderLayout.EAST);
pnlRechts.setPreferredSize(new Dimension(200, 0));
frame.add(pnlMain);
frame.setJMenuBar(menubar);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
initialisieren();
try
{
initVerbindung(new Socket(inetAddr, port));
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void initialisieren() {
pos1 = 26;
pos2 = 26;
regel = "keine";
spielGestartet = true;
spielZustand = new String[3];
steineAufBrett = new int[3];
steineImPool = new int[3];
Random rnd = new Random();
aktSpieler = rnd.nextInt(2) + 1;
if (aktSpieler == 1) {
spielZustand[1] = "SteineSetzen";
spielZustand[2] = "SteineSetzen";
lPlayer.setText("Weiß dran.");
steineAufBrett[1] = 0;
steineImPool[1] = 9;
steineAufBrett[2] = 0;
steineImPool[2] = 9;
brett.spieler = 1;
lAktion.setText(spielZustand[1]);
} else {
spielZustand[2] = "SteineSetzen";
spielZustand[1] = "SteineSetzen";
lPlayer.setText("Schwarz dran.");
steineAufBrett[2] = 0;
steineImPool[2] = 9;
steineAufBrett[1] = 0;
steineImPool[1] = 9;
brett.spieler = 2;
lAktion.setText(spielZustand[2]);
}
pool.init();
brett.init();
}
das gefällt mir momentan am besten...
ja, wir ihr seht, so ganz schlauer bin ich noch nich geworden...würde erstma gerne wissen wollen, ob irgendwas richtig war, ich hoffe der zweite ansatz ^^ und ja ansonsten bitte ich um Lob, Kritik, Blumensträuse ^^
also ich werd das nicht alles durchlesen (die zwei Posts vom 17.12. auch gar nicht gesehen bisher)
kleiner Tipp: wenn du generell an den Grundlagen der Kommunikation arbeitest, dann fange mit einem simplen Programm an,
übe z.B. nur, einen einzelnen String zu übertragen und den auf allen Seiten auszugeben,
aber über Konsole, ganz ohne GUI
in deinem Code sehe ich fast nur Massen an JPanels, Menü-Punkte und langweilige Spiel-Informationen wie
> spielZustand[1] = "SteineSetzen";
> spielZustand[2] = "SteineSetzen";
(12x 'SteineSetzen' in einem Post..)
falls es später um Spiel-Details geht wär das sicher unvermeidbar,
solange du aber noch mit den Sockets an sich kämpfst ist das nur Rauschen,
ich seh gar nicht wo ein Problem besteht
Man kann mit dem ObjectOutputStream (bzw ObjectInputStream) ganze Objecte über TCP/IP versenden. Das ist für den Programmierer sehr komfortabel.
Ob es aber auch sicher ist?