# Multi Clients + Server + Sockets Frage



## wSam (18. November 2006)

Hallo zusammen

Ich habe ein kleines Client - Server Programm geschrieben, bei welchem ich mich als Client beim Server einloggen kann. Jedoch möchte ich jetzt als Client 1 via den Server mit einem beliebigen Client 2 kommunizieren. Daher soll sich der Client zuerst beim Server einloggen, danach bekommt er eine Liste mit allen bereits eingeloggten Clients präsentiert. Aus dieser Liste soll nun ein Client einen anderen Client auswählen können und über den Server zusammen Informationen austauschen. 

Nur habe ich keine Ahnung wie ich bei jedem Client alle Clients welche mit dem Server verbunden sind anzeigen könnte? Ich bräuchte da einen konkreten Tipp.

Und wie könnte ich danach Informationen zwischen den zwei Clients untereinander austauschen (via Server)?

Habe schon das Internet nach Beispiele abgeklappert, fand jedoch nur Client-Server Beispiele.

Ich weiss, ist ein bisschen viel Code und nicht sehr ausgereift ;-). Aber wenns jemand dennoch interessiert (währe froh darüber) und relevant sind ist eigentlich nur der Client und der Sever + Thread:

Hier der Client:

```
public class ClientGUI implements ActionListener, Runnable, MouseListener
{
  JTextField message;

  Socket kkSocket = null;
  PrintWriter out = null;
  BufferedReader in = null;
  BufferedReader stdIn;
  JLabel label;
  JLabel infoLabel;
  JButton send;
  JTextField userNameField;
  JTextField passwordField;
  JButton loginButton;
  
  JTable table;
  JButton connect;

  public void init() throws IOException
  {
    JFrame loginFrame = new JFrame();
    loginFrame.setSize(500, 200);
    loginFrame.setLocation(100, 100);
    loginFrame.setLayout(null);
    loginFrame.setTitle("Client");
    loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    userNameField = new JTextField("test");
    userNameField.setSize(150, 20);
    userNameField.setLocation(330, 20);
    loginFrame.add(userNameField);
    
    passwordField = new JTextField("1234");
    passwordField.setSize(150, 20);
    passwordField.setLocation(330, 50);
    loginFrame.add(passwordField);
    
    loginButton = new JButton("Login");
    loginButton.setSize(150, 20);
    loginButton.setLocation(330, 80);
    loginButton.addActionListener(this);
    loginFrame.add(loginButton);

    infoLabel = new JLabel();
    infoLabel.setSize(150, 20);
    infoLabel.setLocation(330, 110);
    loginFrame.add(infoLabel);
    loginFrame.setVisible(true);
  }
  
  public void showMainFrame() {
    JFrame mainFrame = new JFrame();
    mainFrame.setSize(500, 200);
    mainFrame.setLocation(100, 100);
    mainFrame.setLayout(null);
    mainFrame.setTitle("Client");
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    label = new JLabel("Client: ");
    label.setSize(60, 20);
    label.setLocation(10, 20);
    mainFrame.add(label);

    send = new JButton("Send");
    send.setSize(150, 20);
    send.setLocation(10, 50);
    send.addActionListener(this);
    mainFrame.add(send);
    
    message = new JTextField();
    message.setSize(200, 20);
    message.setLocation(80, 20);
    mainFrame.add(message);
    
    mainFrame.setVisible(true);
  }

  private void connect() throws IOException
  {
    try
    {
      kkSocket = new Socket("localhost", 4444);
      out = new PrintWriter(kkSocket.getOutputStream(), true);
      
      in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream()));
      out.println("username[" + userNameField.getText() + "]");
      out.println("password[" + passwordField.getText() + "]");
      // First line is null
      in.readLine();
      String loginSuccessful = in.readLine();
      if ("true".equals(loginSuccessful)) {
        infoLabel.setText("Login successful");
        
        // Receiving the userlist
        String socketList = in.readLine();
        showSocketList(socketList);
        
        Thread clientThread = null;
        if (clientThread == null) {
          clientThread = new Thread(this, "Client");
          clientThread.start();   // start() method in Thread
        }
      }
      else if ("false".equals(loginSuccessful)) {
        infoLabel.setText("Login not successful");
      }
    } catch (UnknownHostException e)
    {
      System.err.println("Don't know about host: localhost.");
      System.exit(1);
    } catch (IOException e)
    {
      System.err.println("Couldn't get I/O for the connection to: localhost.");
      System.exit(1);
    }
  }

  private void close() throws IOException
  {
    out.close();
    in.close();
    stdIn.close();
    kkSocket.close();
  }

  private void sendMessage()
  {
    String strMessage = message.getText();
    if (strMessage != null)
    {
      out.println(strMessage);
      message.setText("");
    }
  }

  public void actionPerformed(ActionEvent e)
  {
    String cmd = e.getActionCommand();
    if (cmd.equals("Send"))
    {
      sendMessage();
    }
    if (cmd.equals("Login"))
    {
      try
      {
        connect();
      }
      catch (IOException e1)
      {
        // TODO Auto-generated catch block
        e1.printStackTrace();
      }
    }
    if (cmd.equals("Connect"))
    {
      System.out.println("LOGGER - -> Connecting... to row number " + table.getSelectedRow());
      playGame(table.getSelectedRow());
    }
  }

  private void playGame(int userId)
  {
    out.println("playgame[" + userId + "]");
  }

  public void run()
  {
    String input = null;
    
    while (true) {
      try
      {
        while ((input = in.readLine()) != null)
        {
          System.out.println("LOGGER - Client side: " + input);
        }
      }
      catch (IOException e1)
      {
        // TODO Auto-generated catch block
        e1.printStackTrace();
      }
      
      
      
      try {
        Thread.sleep(1000);
      }
      catch(InterruptedException e)
      {
        e.printStackTrace();
      }
    }  
  }
  
  private void showSocketList(String socketList) {
    
    JFrame userListFrame = new JFrame("User List");
    userListFrame.setLocation(100, 100);
    userListFrame.setSize(500, 300);
    userListFrame.setVisible(true);
    userListFrame.setLayout(null);
    
    String[][] DATA = {
        {socketList.substring(10, 14), "not aviable"}
      };
    
      String[] COLHEADS = {
        "Username", "Status"
      };
      
    table = new JTable(DATA, COLHEADS);
    table.setRowHeight(15);
    table.setSize(500, 200);
    table.setLocation(0,0);
    table.addMouseListener(this);
    
    JScrollPane scroll = new JScrollPane(table);
    scroll.setSize(500, 200);
    scroll.setLocation(0,0);
    userListFrame.add(scroll); 
    
    //userListFrame.add(new JScrollPane(table), null);
    
    connect = new JButton("Connect");
    connect.setSize(150, 20);
    connect.setLocation(10, 220);
    connect.addActionListener(this);
    userListFrame.add(connect);
    
    userListFrame.setVisible(true);
  }

  public void mouseClicked(MouseEvent arg0)
  {
    System.out.println("TS: " + table.getSelectedRow());
    // TODO Auto-generated method stub
    
  }

  public void mousePressed(MouseEvent arg0)
  {
    // TODO Auto-generated method stub
    
  }

  public void mouseReleased(MouseEvent arg0)
  {
    // TODO Auto-generated method stub
    
  }

  public void mouseEntered(MouseEvent arg0)
  {
    // TODO Auto-generated method stub
    
  }

  public void mouseExited(MouseEvent arg0)
  {
    // TODO Auto-generated method stub
    
  }
}
```


Server:

```
public class KKMultiServer
{
  public void startServer() throws IOException
  {
    ServerSocket serverSocket = null;
    boolean listening = true;

    try
    {
      serverSocket = new ServerSocket(4444);
      System.out.println("Server is listening on port: 4444...");
    } catch (IOException e)
    {
      System.err.println("Could not listen on port: 4444.");
      System.exit(-1);
    }

    while (listening)
    {
      KKMultiServerThread sThread = new KKMultiServerThread(serverSocket.accept());
      sThread.start();
    }
    serverSocket.close();
  }
}
```

Server Thread:

```
public class KKMultiServerThread extends Thread
{
  private Socket socket = null;
  
  private static HashMap sockets = new HashMap();
  private static HashMap users = new HashMap();

  public KKMultiServerThread(Socket socket)
  {
    super("KKMultiServerThread");
    
    
    // Loading the users into the users map
    users.put("username[hans]", "password[abc]");
    users.put("username[test]", "password[1234]");
    
    
    this.socket = socket;
  }

  public void run()
  {
    try
    {
      PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
      BufferedReader in = new BufferedReader(new InputStreamReader(socket
          .getInputStream()));

      String inputLine, outputLine;
      KnockKnockProtocol kkp = new KnockKnockProtocol();
      outputLine = kkp.processInput(null);
      out.println(outputLine);

      String userName = in.readLine();
      String password = in.readLine();
      
      if (users.containsKey(userName) && users.get(userName).equals(password))
      {
        // The map with the connected sockets
        // Login successfully = true else false
        out.println("true");
        // Updating the list with the users
        sockets.put(userName, socket.getRemoteSocketAddress());
        out.println(sockets.toString());
        

        while ((inputLine = in.readLine()) != null)
        {
          System.out.println("LOGGER - waiting...");
          outputLine = kkp.processInput(inputLine);
          System.out.println("LOGGER - " + outputLine);
          out.println(outputLine);
          if (outputLine.equals("Bye"))
            break;
        }
      }
      else
      {
        System.out.println("LOGGER - Wrong username/password");
        out.println("false");
      }

      out.close();
      in.close();
      socket.close();

    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }
}
```

Protikoll:

```
public class KnockKnockProtocol {
  
    public String processInput(String theInput) {
      if (theInput != null) {
        if (theInput.startsWith("playgame")) {
          System.out.println("LOGGER - playing game with " + theInput);
        }
      }
      
      return theInput;
    }
}
```

Start Klasse für alles:

```
public class StartChess {

	public static void main(String[] args)
	  {
	    ClientStart cStart = new ClientStart();
	    cStart.startClient();
      
           ClientStart cStart2 = new ClientStart();
           cStart2.startClient();
      
	    KKMultiServer sStart = new KKMultiServer();
	    try {
			sStart.startServer();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	  }
}
```

Hier ist der Start für den Client:

```
public class ClientStart
{

  public void startClient()
  {
    // Schedule a job for the event-dispatching thread:
    // creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable()
    {
      public void run()
      {
        ClientGUI gui = new ClientGUI();
        try
        {
          gui.init();
        } catch (IOException e)
        {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    });
  }

}
```


Vielen Dank im Voraus und Gruss


----------



## matdacat (20. November 2006)

wSam hat gesagt.:


> Nur habe ich keine Ahnung wie ich bei jedem Client alle Clients welche mit dem Server verbunden sind anzeigen könnte? Ich bräuchte da einen konkreten Tipp.


Der Server verwaltet eine Liste der eingeloggten Clients und übermittelt diese nach dem Einloggen eines neues Clients. Hast Du schon daran gedacht, RMI zu verwenden? Damit wärs dann ziemlich einfach, ganze Objekte zu versenden.


----------



## wSam (20. November 2006)

Hmm ja wäre eine Möglichkeit.
Aber ist dies grundsätzlich so möglich wie ich das möchte?


----------



## matdacat (20. November 2006)

wSam hat gesagt.:


> Aber ist dies grundsätzlich so möglich wie ich das möchte?


Definitiv! ;-) 

Aber wie gesagt: verwende RMI, das nimmt dir viel Arbeit ab und sollte für deine Zwecke (Schachspiel?) auch performancetechnnisch mehr als ausreichen.

Tom hat ja bereits einiges Hilfreiches zu RMI gepostet, z.B. hier.


----------



## wSam (20. November 2006)

@matdacat

Ok werde mir RMI mal anschauen. 
Ja es soll tatsächlich ein Schachspiel geben (also das Spiel habe ich schon (fast), nur die Netzwerkfunktionalität noch nicht). Woher weisst du den dass wieder?


----------



## matdacat (21. November 2006)

Och, reine Intuition ;-)
Viel Erfolg!


----------



## wSam (21. November 2006)

@matdacat

 Danke.


----------

