Also mein Problem ist efinkelt. Sitz an dem Problem schon mehr als eine Woche. Detail am Rande: das soll Bomberman übers Netzwerk werden.
Auf der Client-Seite gibt es folgenedes:
ClientModule.java: Das Herzstück des Clients
ClientConnect.java: So Connected man zum Server (ihr seht schon, ich war faul und hab mit dem Designer gearbeitet)
ClientLounge.java: das "Chat-Fenster":
Die Server Seite:
BomberServer.java: Wartet auf neue Clients
Player.java: baut die Verbindung auf. Erster Austausch von Daten.
Und nun eine kurze Erklärung was so passiert wenn ein Client sich auf den Server connected:
(Die Abläufe müsst ihr euch teilweise gleichzeitig vorstellen)
Server.BomberServer starten: wartet auf eingehende Verbindung
Client.ClientConnect starten: öffnet den Verbindungs-Dialog ->OK
Client.ClientConnect startet anschließend Client.ClientModule
Client.ClientModule öffnet Verbindung zum Server
Client.ClientModule wartet auf Initialisierungs-String vom Server
Server.BomberServer startet bei neuer Verbindung Server.PLayer
Server.Player sendet String um Name und Color vom Client zu erhalten
Client.ClientModule sendet Name und Color
Client.ClientModule wartet auf positive Antwort
Server.Player sendet positive Antwort
Server.Player startet sich selbst als Thread: der Thread wartet auf neue
Strings aus dem BufferedReader ( is.readline() )
Client.ClientModule erhält positive Antwort
Client.ClientModule öffnet Client.ClientLounge
Client.ClientLounge kann Texte aus einem Textfeld verschicken (ActionEvent)
Server.Player erhält keine Strings vom Client, sondern bekommt immer nur
null-Strings und blockt den Thread nicht
Hoffe ihr könnt mir helfen :!: Ansonsten wirds nichts mit ner guten Programmiernote :###
mfg, Alc
P.S.: Hoffe mein Thread is nicht überladen!
Auf der Client-Seite gibt es folgenedes:
ClientModule.java: Das Herzstück des Clients
Code:
package Client;
import java.io.*;
import java.net.*;
import java.util.*;
/**
*
* @author Clemens Rögner - dv20020456
*/
public class ClientModule extends Thread{
private boolean run = true;
private Socket sock;
public BufferedReader in;
public PrintWriter out;
private TreeMap<String, ArrayList<msgListener>> msgL = new TreeMap<String, ArrayList<msgListener>>();
public ClientModule(String host, int port, String name, String color) throws ConnectException{
try {
//Initialising
sock = new Socket(host, port);
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
out = new PrintWriter(sock.getOutputStream());
//waiting for "login data"
String s = in.readLine();
if(!s.equals("login data"))
throw new ConnectException();
//sending name and color
send("login " + name + " " + color);
//waiting for ack "login ok". if "login bad" an Exception will e thrown
s = in.readLine();
if(s==null || !s.equals("login ok"))
throw new ConnectException();
this.start();
}
catch (UnknownHostException e) {
throw new ConnectException("UnknownHostException - " + e);
}
catch (EOFException e) {
throw new ConnectException("EOFException - " + e.getMessage());
}
catch (IOException e) {
throw new ConnectException("IOException - " + e);
}
finally {
close();
}
}
public void run() {
//Listening Thread for receiving msg. only started, when Server sent "login ok"
while(run) {
//unimportant
}
}
public boolean addMsgListener(String key, msgListener l) {
//unimportant
return true;
}
public boolean removeMsgListener(String key, msgListener l) {
//unimportant
return true;
}
public boolean send(String s) { //sending Method
if(s==null)
return false;
try{
out.println(s);
out.flush();
}
catch(Exception e) {
close();
return false;
}
return true;
}
public void close() {
run = false;
try {
if(in != null) in.close();
if(out != null) out.close();
if(sock != null) sock.close();
}
catch(IOException e) {
System.err.println("Fehler 2: " + e);
}
}
}
ClientConnect.java: So Connected man zum Server (ihr seht schon, ich war faul und hab mit dem Designer gearbeitet)
Code:
package Client;
import javax.swing.*;
/**
*
* @author Clemens Rögner - dv20020456
*/
public class ClientConnect extends javax.swing.JFrame {
private ClientModule server;
/** Creates new form ClientConnect */
public ClientConnect() {
initComponents();
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
jPanel2 = new javax.swing.JPanel();
jLabel2 = new javax.swing.JLabel();
JTname = new javax.swing.JTextField();
jPanel3 = new javax.swing.JPanel();
jLabel3 = new javax.swing.JLabel();
JCcolor = new javax.swing.JComboBox();
jPanel4 = new javax.swing.JPanel();
jLabel4 = new javax.swing.JLabel();
JTip = new javax.swing.JTextField();
jPanel5 = new javax.swing.JPanel();
jLabel5 = new javax.swing.JLabel();
JTport = new javax.swing.JTextField();
jPanel6 = new javax.swing.JPanel();
JBconnect = new javax.swing.JButton();
jPanel7 = new javax.swing.JPanel();
JLstatus = new javax.swing.JLabel();
getContentPane().setLayout(new java.awt.GridLayout(7, 1));
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Bomberman - Connect");
jLabel1.setText("Bomberman");
jPanel1.add(jLabel1);
getContentPane().add(jPanel1);
jLabel2.setText("Name");
jPanel2.add(jLabel2);
JTname.setMinimumSize(new java.awt.Dimension(100, 19));
JTname.setPreferredSize(new java.awt.Dimension(100, 19));
jPanel2.add(JTname);
getContentPane().add(jPanel2);
jLabel3.setText("Figur");
jPanel3.add(jLabel3);
JCcolor.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Blue", "Red", "Green", "Yellow" }));
JCcolor.setPreferredSize(new java.awt.Dimension(100, 22));
jPanel3.add(JCcolor);
getContentPane().add(jPanel3);
jLabel4.setText("Server");
jPanel4.add(jLabel4);
JTip.setText("127.0.0.1");
JTip.setPreferredSize(new java.awt.Dimension(100, 19));
jPanel4.add(JTip);
getContentPane().add(jPanel4);
jLabel5.setText("Port");
jPanel5.add(jLabel5);
JTport.setText("8000");
JTport.setPreferredSize(new java.awt.Dimension(100, 19));
jPanel5.add(JTport);
getContentPane().add(jPanel5);
JBconnect.setText("Connect");
JBconnect.setPreferredSize(new java.awt.Dimension(100, 23));
JBconnect.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
JBconnectActionPerformed(evt);
}
});
jPanel6.add(JBconnect);
getContentPane().add(jPanel6);
JLstatus.setText("Fill in and Connect");
jPanel7.add(JLstatus);
getContentPane().add(jPanel7);
pack();
}
// </editor-fold>
private void JBconnectActionPerformed(java.awt.event.ActionEvent evt) {
if((JTname.getText() != null) && (JTip.getText() != null) && (JTport.getText() != null)) {
try {
server = new ClientModule(JTip.getText(), new Integer(JTport.getText()), JTname.getText(), JCcolor.getSelectedItem().toString());
new ClientLounge(server);
this.dispose();
}
catch(ConnectException ce) {
JLstatus.setText("Error: " + ce);
}
}
else {
JLstatus.setText("Wrong Parameters!");
}
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ClientConnect().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton JBconnect;
private javax.swing.JComboBox JCcolor;
private javax.swing.JLabel JLstatus;
private javax.swing.JTextField JTip;
private javax.swing.JTextField JTname;
private javax.swing.JTextField JTport;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JPanel jPanel3;
private javax.swing.JPanel jPanel4;
private javax.swing.JPanel jPanel5;
private javax.swing.JPanel jPanel6;
private javax.swing.JPanel jPanel7;
// End of variables declaration
}
ClientLounge.java: das "Chat-Fenster":
Code:
/*
* ClientLounge.java
*
* Created on 24. März 2006, 23:15
*/
package Client;
import javax.swing.*;
/**
*
* @author Clemens Rögner - dv20020456
*/
public class ClientLounge extends javax.swing.JFrame {
ClientModule server;
DefaultListModel msg = new DefaultListModel();
/** Creates new form ClientLounge */
public ClientLounge(ClientModule server) {
initComponents();
this.server = server;
this.setVisible(true);
this.LImsg.setModel(msg);
//Adding Listener für receiving Chat Messages
server.addMsgListener("lounge", new msgHandler(){
public void gotMsg(String[] paras) {
if((paras.length>=3) && (paras[0].equals("msg"))) {
String m = "";
for(int i=2; i<paras.length; i++) {
m += paras[i];
}
msg.addElement(m);
}
}
});
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">
private void initComponents() {
LIplayer = new javax.swing.JList();
Tmsg = new javax.swing.JTextField();
LImsg = new javax.swing.JList();
jMenuBar1 = new javax.swing.JMenuBar();
MGame = new javax.swing.JMenu();
MInfo = new javax.swing.JMenuItem();
MDisconnect = new javax.swing.JMenuItem();
MExit = new javax.swing.JMenuItem();
MOptions = new javax.swing.JMenu();
MUI = new javax.swing.JMenuItem();
getContentPane().setLayout(new java.awt.BorderLayout(3, 3));
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Bomberman - Lounge");
LIplayer.setPreferredSize(new java.awt.Dimension(100, 0));
getContentPane().add(LIplayer, java.awt.BorderLayout.EAST);
Tmsg.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
TmsgActionPerformed(evt);
}
});
getContentPane().add(Tmsg, java.awt.BorderLayout.SOUTH);
getContentPane().add(LImsg, java.awt.BorderLayout.CENTER);
MGame.setText("Game");
MInfo.setText("Server Info");
MGame.add(MInfo);
MDisconnect.setText("Disconnect");
MGame.add(MDisconnect);
MExit.setText("Exit");
MGame.add(MExit);
jMenuBar1.add(MGame);
MOptions.setText("Options");
MUI.setText("Ui Options");
MOptions.add(MUI);
jMenuBar1.add(MOptions);
setJMenuBar(jMenuBar1);
pack();
}
// </editor-fold>
private void TmsgActionPerformed(java.awt.event.ActionEvent evt) {
if(server.send("lounge msg " + Tmsg.getText())) //Sending a chat-msg to the Server
System.out.println("sending msg " + Tmsg.getText());
}
// Variables declaration - do not modify
private javax.swing.JList LImsg;
private javax.swing.JList LIplayer;
private javax.swing.JMenuItem MDisconnect;
private javax.swing.JMenuItem MExit;
private javax.swing.JMenu MGame;
private javax.swing.JMenuItem MInfo;
private javax.swing.JMenu MOptions;
private javax.swing.JMenuItem MUI;
private javax.swing.JTextField Tmsg;
private javax.swing.JMenuBar jMenuBar1;
// End of variables declaration
}
Die Server Seite:
BomberServer.java: Wartet auf neue Clients
Code:
package Server;
import java.io.*;
import java.net.*;
import java.util.*;
/**
*
* @author dv20020456
*/
public class BomberServer {
public static int PORT = 8000;
private static boolean running = false;
/** Creates a new instance of BomberServer */
public BomberServer() {
}
public static void main (String args[]) {
ServerSocket listen = null;
try {
listen = new ServerSocket(PORT);
listen.setSoTimeout(2000);
printMsg("Server is running: " + listen);
running = true;
while(running) {
try {
//Waiting for Players
Socket s = listen.accept();
System.out.println("new Player: " + s);
//Creating new Player. Exchange of data and starting Listening Thread
Player p = new Player(s);
//Adding Listener for Chat-Msg from Players
p.addMsgListener("lounge", new msgHandler() {
public void gotMsg(Player p, String[] paras) {
printMsg("GOT MSG" );
String s = " ";
for(int i=0; i<paras.length; i++) {
s += paras[i] + " ";
}
Player.sendToAll("lounge msg " + p.name + s);
}
});
}
catch(SocketTimeoutException e) {}
}
}
catch(IOException ioe) {
System.out.println("Fehler:" + ioe.toString());
}
finally {
try {
if(listen != null) listen.close();
System.out.println("Bye...");
}
catch(IOException e) {}
}
}
public static void printMsg(String s) {
System.out.println(s);
}
protected static void loungeMsg(Player p , String s) {
Player.sendToAll("lounge msg " + p.name + " " + s);
}
}
Player.java: baut die Verbindung auf. Erster Austausch von Daten.
Code:
/*
* Player.java
*
* Created on 09. März 2006, 09:48
*
* To change this template, choose Tools | Options and locate the template under
* the Source Creation and Management node. Right-click the template and choose
* Open. You can then make changes to the template in the Source Editor.
*/
package Server;
import java.io.*;
import java.net.*;
import java.util.*;
/**
*
* @author dv20020456
*/
public class Player extends Thread{
protected static TreeMap<String,Player> all = new TreeMap<String,Player>();
protected TreeMap<String, ArrayList<msgListener>> msgL = new TreeMap<String, ArrayList<msgListener>>();
protected Game g = null;
protected String name;
protected String color;
private Socket s;
private BufferedReader is = null;
private PrintStream os = null;
private boolean run = true;
/** Creates a new instance of Player */
public Player(Socket s) {
this.s = s;
try {
is = new BufferedReader(new InputStreamReader(s.getInputStream()));
os = new PrintStream(s.getOutputStream());
//Ready for Receiving Data
if(!send("login data")) {
close();
}
//Waiting for Data
String request = is.readLine();
String[] log = request.split(" ");
if(log.length == 3 && log[0].equals("login")) { //If Data-String ok
if(!send("login ok")) {
close();
}
this.name = log[1];
this.color = log[2];
}
else {
if(!send("login bad")) {
}
}
}
catch(IOException ioe) {
BomberServer.printMsg("Error: " + ioe);
close();
}
catch(Exception e) {
BomberServer.printMsg(e.toString());
close();
}
//Adding Player to the List
all.put(this.name, this);
//Starting Thread
this.start();
}
public void run() {
try {
while(true) {
String str = is.readLine(); //Bekomme immer "null"
BomberServer.printMsg("got it: " + str);
}
}
catch(IOException ioe) {
BomberServer.printMsg("Error: " + ioe);
}
finally {
close();
}
}
protected boolean send(String s) { //sending Method
if(s==null)
return false;
try{
os.println(s);
os.flush();
}
catch(Exception e) {
close();
return false;
}
return true;
}
protected void doCmd(String s) {
//unimportant
}
protected static void sendToAll(String s) {
Iterator i = all.keySet().iterator();
while(i.hasNext()) {
all.get((String)i.next()).send(s);
}
}
public boolean addMsgListener(String key, msgListener l) {
//unimportant
return true;
}
public boolean removeMsgListener(String key, msgListener l) {
//unimportant
return true;
}
private void close() {
run = false;
all.remove(this.name);
try {
if(is != null) is.close();
if(os != null) os.close();
if(s != null) s.close();
}
catch(IOException e) {
BomberServer.printMsg(e.toString());
}
finally {
sendToAll("disconnect " + name);
}
}
}
Und nun eine kurze Erklärung was so passiert wenn ein Client sich auf den Server connected:
(Die Abläufe müsst ihr euch teilweise gleichzeitig vorstellen)
Server.BomberServer starten: wartet auf eingehende Verbindung
Client.ClientConnect starten: öffnet den Verbindungs-Dialog ->OK
Client.ClientConnect startet anschließend Client.ClientModule
Client.ClientModule öffnet Verbindung zum Server
Client.ClientModule wartet auf Initialisierungs-String vom Server
Server.BomberServer startet bei neuer Verbindung Server.PLayer
Server.Player sendet String um Name und Color vom Client zu erhalten
Client.ClientModule sendet Name und Color
Client.ClientModule wartet auf positive Antwort
Server.Player sendet positive Antwort
Server.Player startet sich selbst als Thread: der Thread wartet auf neue
Strings aus dem BufferedReader ( is.readline() )
Client.ClientModule erhält positive Antwort
Client.ClientModule öffnet Client.ClientLounge
Client.ClientLounge kann Texte aus einem Textfeld verschicken (ActionEvent)
Server.Player erhält keine Strings vom Client, sondern bekommt immer nur
null-Strings und blockt den Thread nicht
Hoffe ihr könnt mir helfen :!: Ansonsten wirds nichts mit ner guten Programmiernote :###
mfg, Alc
P.S.: Hoffe mein Thread is nicht überladen!