2014-10-09 60 views
0

程序的過程去像這樣:Java的插座 - 發送任何客戶端輸入到所有其他客戶端使用線程

在服務器:

-Open new window with GUI 
-Start a serversocket on port 1500 
-Await a client to connect 
-Accept the client 
-Wait to recieve their username 
-Send their client number 
-Start a new Thread for the client 
-Store playernames, positions and the threads 

在主題:

while循環:

-Wait to Receive Object from client, where the Object is a Vector3f (float,float,float) 
-Set the ArrayList of Vector3f, where the index is clientnumber, to equal the Object recieved from the client 
-Send the client the arraylist 

在客戶端:

-Join server at specified ip 
-Send username 
-Recieve clientnumber 

while循環:

-Send Vector3f 
-recieve arraylist of Vector3f 

但是...我認爲這是可行的。我認爲客戶會正確連接,並且每個客戶都會收到每個其他玩家位置的陣列列表(Vector3f)。這似乎爲第4個客戶機連接工作,直到:

java.util.ConcurrentModificationException 

不知道如何解決這個問題?

這裏是所有代碼:

客戶:

package main; 

import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.Socket; 
import java.util.ArrayList; 

public class Client { 
    private Socket socket = null; 
    private ObjectInputStream inStream = null; 
    private ObjectOutputStream outStream = null; 
    String name = "bob"; 
    int port; 
    String ip; 
    Vector3f v3f = new Vector3f(0, 0, 0); 
    int clientnumber = 0; 
    int numberofclients = 0; 
    ArrayList<Vector3f> positions = new ArrayList<Vector3f>(); 

    public Client(int port, String ip, String name) { 
     this.port = port; 
     this.ip = ip; 
     this.name = name; 
     startClient(); 
    } 

    public void startClient() { 
     try { 
      socket = new Socket(ip, port); 
      System.out.println("Connected"); 
      outStream = new ObjectOutputStream(socket.getOutputStream());//send name 
      outStream.writeObject(name); 

      inStream = new ObjectInputStream(socket.getInputStream());//recieve client number 
      clientnumber = (int) inStream.readObject(); 

      while (true) { 
       v3f = new Vector3f(Math.random()*10+1, Math.random()*10+1, Math.random()*10+1); 
       outStream = new ObjectOutputStream(socket.getOutputStream());//send position 
       outStream.writeObject(v3f); 

       inStream = new ObjectInputStream(socket.getInputStream());//recieve position(s) 
       positions = (ArrayList<Vector3f>) inStream.readObject(); 

       numberofclients = positions.size(); 
      } 

     } catch (Exception e) { 
      System.err.println("Client Error: " + e.getMessage()); 
      System.err.println("Localized: " + e.getLocalizedMessage()); 
      System.err.println("Stack Trace: " + e.getStackTrace()); 
     } 
    } 

    public static void main(String[] args) { 
     new Client(1500, "localHost", "bob"); 
    } 
} 

服務器:

package main; 

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Toolkit; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.InetAddress; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.net.URL; 
import java.text.SimpleDateFormat; 
import java.util.ArrayList; 
import java.util.Calendar; 

import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.JTextField; 

public class Server { 

    static JFrame f = new JFrame(); 
    static JPanel p = new JPanel(); 
    static JLabel info = new JLabel(); 
    private ServerSocket serverSocket = null; 
    private Socket socket = null; 
    private boolean connection = false; 
    private boolean serverisrunning = true; 
    private int port; 
    static JTextArea jt = new JTextArea(); 
    public static boolean showtimestamp = false; 
    private JScrollPane sc = new JScrollPane(jt, 
      JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
      JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 
    String timeStamp = new SimpleDateFormat("HH:mm:ss").format(Calendar 
      .getInstance().getTime()); 
    String defaulttext = System.getProperty("user.name") + "/" + getIp() 
      + " > "; 
    String error = "Error - "; 
    String badcom = " Is Not Recognised As A Valid Command"; 
    String baduse = "Incorrect Use"; 
    String tftext = ""; 
    ObjectInputStream inStream = null; 
    ObjectOutputStream outStream = null; 
    JTextField tf = new JTextField("/"); 
    static ArrayList<EchoThread> clients = new ArrayList<EchoThread>(); 
    static ArrayList<String> clientnames = new ArrayList<String>(); 
    static ArrayList<Vector3f> clientpos = new ArrayList<Vector3f>(); 
    Dimension ss = Toolkit.getDefaultToolkit().getScreenSize(); 

    public Server(int port) { 
     this.port = port; 

     f.setTitle("Server"); 
     f.setBounds(ss.width - 750, 50, 701, 350); 
     f.setResizable(false); 
     f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); 
     f.setAlwaysOnTop(true); 
     f.setLayout(null); 
     f.add(p); 
     f.addWindowListener(new WindowAdapter() { 
      public void windowClosing(WindowEvent we) { 
       if (connection) { 
        try { 
         socket.close(); 
         serverSocket.close(); 
        } catch (IOException e) { 
        } 
       } 
       System.exit(0); 
      } 
     }); 

     f.add(sc); 
     sc.setBounds(151, 0, 560, 300); 
     jt.setBackground(Color.BLACK); 
     jt.setForeground(Color.WHITE); 
     jt.setLineWrap(true); 
     jt.setEditable(false); 
     append("Hello World"); 

     f.add(info); 
     info.setOpaque(true); 
     info.setBounds(0, 0, 150, 19); 
     info.setBackground(Color.RED); 
     info.setText("Clients Connected: " + clients.size()); 

     f.add(tf); 
     tf.setBounds(151, 298, 544, 23); 
     tf.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       tftext = tf.getText(); 
       RunCommand(tftext); 
       tf.setText("/"); 
      } 
     }); 
     tf.setBackground(Color.BLACK); 
     tf.setForeground(Color.WHITE); 

     f.getContentPane().setBackground(Color.BLACK); 
     f.setVisible(true); 
     startServer(); 
    } 

    protected void RunCommand(String txt) { 
     serverMessage("'" + txt.replace("/", "") + "'\n"); 
     if (txt.contains("/")) { 
      if (txt.equals("/")) { 
       return; 
      } 
      String t = txt.toLowerCase().replace("/", ""); 
      if (t.contains("setshowtime")) { 
       if (t.endsWith(" true")) { 
        showtimestamp = true; 
        append("ShowTimeStamp - true"); 
       } else if (t.endsWith(" false")) { 
        showtimestamp = false; 
        append("ShowTimeStamp - false"); 
       } else { 
        append(error + baduse + " '" + txt + "' " 
          + "\nCorrect Use: SetShowTime true/false"); 
       } 
      } else if (t.contains("say ")) { 
       message(t.replace("say ", "")); 
      } else if (t.contains("hello")) { 
       append("Hi " + System.getProperty("user.name")); 
      } else if (t.contains("stop")) { 
       serverMessage("Server Starting\nInitialising socket connections:"); 
       serverisrunning = false; 
      } else if (t.contains("kick")) { 
       int indexOf = t.indexOf('c'); 
       String name = t.substring(indexOf + 2).trim(); 
       serverMessage("Kicking Player " + name); 
       for (int i = 0; i < clientnames.size(); i++) { 
        if (clientnames.get(i).toLowerCase().contains(name)) { 
         append("\n'" + name + "' was found: " 
           + clientnames.get(i)); 
         p.remove(clients.get(i).clientinfo); 
         p.revalidate(); 
         f.validate(); 
         f.repaint(); 
         clients.get(i).clientinfo.setVisible(false); 
         clients.remove(i); 
         clientnames.remove(i); 
         info.setText("Clients Connected: " + clients.size()); 
        } 
       } 
      } else {// if none of the other commands 
       append(error + "'" + t + "'" + badcom); 
      } 
     } else { 
      // dunno 
     } 
    } 

    public void sendToAll(Object message){ 
     for(EchoThread client : clients) 
      client.write(clientpos.get(clients.indexOf(client))); 
    } 

    public static void removeClient(int i) { 
     p.remove(clients.get(i).clientinfo); 
     p.revalidate(); 
     f.validate(); 
     f.repaint(); 
     clients.get(i).clientinfo.setVisible(false); 
     clients.remove(i); 
     clientnames.remove(i); 
     clientpos.remove(i); 
     info.setText("Clients Connected: " + clients.size()); 
    } 

    public void message(String msg) { 
     timeStamp = new SimpleDateFormat("HH:mm-ss").format(Calendar 
       .getInstance().getTime()); 
     jt.append(" [" + timeStamp + "] " + msg); 
     jt.append("\n" + defaulttext); 
     jt.setCaretPosition(jt.getDocument().getLength()); 
    } 

    public void append(String text) { 
     timeStamp = new SimpleDateFormat("HH:mm-ss").format(Calendar 
       .getInstance().getTime()); 
     if (showtimestamp) { 
      jt.append(" [" + timeStamp + "] "); 
     } 
     jt.append(text); 
     jt.append("\n" + defaulttext); 
     jt.setCaretPosition(jt.getDocument().getLength()); 
    } 

    public static void serverMessage(String text) { 
     jt.append(text); 
     jt.setCaretPosition(jt.getDocument().getLength()); 
    } 

    public void startServer() { 
     try { 
      serverSocket = new ServerSocket(port); 
      append("\nPort: " + port + "\nLocal IP address: " 
        + InetAddress.getLocalHost().getHostAddress() 
        + "\nExternal IP address: " + getIp() 
        + "\nType 'stop' to stop listening for clients...\n"); 

      while (serverisrunning) { 
       if (clients.size() < 15) { 
        socket = serverSocket.accept(); 

        inStream = new ObjectInputStream(socket.getInputStream());// recieve username 
        String name = (String) inStream.readObject(); 
        clientnames.add(name); 
        System.out.println(name + " Connected"); 
        outStream = new ObjectOutputStream(socket.getOutputStream());// send client number 
        outStream.writeObject(clients.size() + 1); 

        clientpos.add(new Vector3f()); 

        clients.add(new EchoThread(socket)); 
        clients.get(clients.size() - 1).start(); 
        clients.get(clients.size() - 1).clientindex = (clients 
          .size()); 
        clients.get(clients.size() - 1).clientname = clientnames 
          .get((clients.size() - 1)); 


        connection = true; 

        timeStamp = new SimpleDateFormat("HH:mm-ss") 
          .format(Calendar.getInstance().getTime()); 
        append("Client Connected: " + clients.size() + "\n" 
          + clients + "\n" + "Client IP: " 
          + socket.getRemoteSocketAddress() + "\n\n###### " 
          + name + " Connected " + timeStamp + " ######\n"); 

        for (int i = 0; i < clients.size(); i++) { 
         if (!clients.get(i).isAlive()) { 
          clients.remove(i); 
          clientnames.remove(i); 
         } 
        } 
       } 

       info.setText("Clients Connected: " + clients.size()); 
      } 

     } catch (Exception e) { 
     } 
    } 

    public static String getIp() { 
     URL whatismyip; 
     try { 
      whatismyip = new URL("http://checkip.amazonaws.com"); 

      BufferedReader in = null; 
      in = new BufferedReader(new InputStreamReader(
        whatismyip.openStream())); 
      String ip = in.readLine(); 

      if (in != null) { 
       in.close(); 
      } 

      return ip; 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    public static void main(String[] args) { 
     new Server(1500); 
    } 
} 

Vector3f:

package main; 

import java.io.Serializable; 
import javax.swing.JTextArea; 

public class Vector3f implements Serializable { 

    public double x; 
    public double y; 
    public double z; 

    public Vector3f(int x, int y, int z) { 
     this.x = x; 
     this.y = y; 
     this.z = z; 
    } 

    public Vector3f(float x, float y, float z) { 
     this.x = x; 
     this.y = y; 
     this.z = z; 
    } 

    public Vector3f(double x, double y, double z) { 
     this.x = x; 
     this.y = y; 
     this.z = z; 
    } 

    public Vector3f() { 
     this.x = 0; 
     this.y = 0; 
     this.z = 0; 
    } 

    public void OutputToConsole(String additionaltext) { 
     System.out.println(additionaltext + " x:" + x + " y:" + y + " z:" + z); 
    } 

    public void appendToTextArea(JTextArea ta, String additionaltext) { 
     ta.append(additionaltext + " x:" + x + " y:" + y + " z:" + z); 
    } 

} 

EchoThread:

package main; 

import java.awt.Color; 
import java.awt.Font; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.Socket; 

import javax.swing.JFrame; 
import javax.swing.JLabel; 

public class EchoThread extends Thread { 
    volatile boolean finished = false; 
    protected Socket socket; 
    boolean isrunning = false; 
    boolean edited = false; 
    ObjectInputStream inStream = null; 
    ObjectOutputStream outStream = null; 
    Vector3f v3f = new Vector3f(0, 0, 0); 
    JLabel clientinfo = new JLabel(); 
    JFrame f; 
    int clientindex = 0; 
    String clientname = ""; 
    int numberofclients = Server.clients.size(); 

    public EchoThread(Socket clientSocket) { 
     this.socket = clientSocket; 

     f = Server.f; 
     f.add(clientinfo); 
     clientinfo.setOpaque(true); 
     clientinfo.setBounds(0, 20 + (20 * Server.clients.size()), 150, 19); 
     clientinfo.setBackground(Color.GREEN); 

    } 

    public void run() { 
     while (!finished) { 
      numberofclients = Server.clients.size(); 
      try { 
       inStream = new ObjectInputStream(socket.getInputStream()); 
       v3f = (Vector3f) inStream.readObject(); 

       clientinfo.setText("[" + clientindex + "] " + clientname + ": " 
         + (int) v3f.x + "," + (int) v3f.y + "," + (int) v3f.z); 
       FontToFit(clientinfo); 

       Server.clientpos.set(clientindex-1, v3f); 

       outStream = new ObjectOutputStream(socket.getOutputStream()); 
       outStream.writeObject(Server.clientpos); 


      } catch (Exception e) { 
      System.out.println(e); 
       try { 
        //Server.removeClient(clientindex - 1); 
        end(); 
        Server.serverMessage(clientname + " Disconnected"); 
        socket.shutdownOutput(); 
        inStream.close(); 
        outStream.close(); 
        socket.shutdownInput(); 
        socket.close(); 
       } catch (IOException e1) { 
       } 
       return; 
      } 
     } 
    } 

    public void write(Object obj) { 
     try{ 
      outStream.writeObject(obj); 
     } 
     catch(IOException e){ e.printStackTrace(); } 
    } 

    public void end() { 
     finished = true; 
    } 

    public void FontToFit(JLabel label) { 
     Font labelFont = label.getFont(); 
     String labelText = label.getText(); 

     double stringWidth = label.getFontMetrics(labelFont).stringWidth(
       labelText); 
     double componentWidth = label.getWidth(); 

     // Find out how much the font can grow in width. 
     double widthRatio = (double) componentWidth/(double) stringWidth; 

     double newFontSize = (int) (labelFont.getSize() * widthRatio); 
     double componentHeight = label.getHeight(); 

     // Pick a new font size so it will not be larger than the height of 
     // label. 
     double fontSizeToUse = Math.min(newFontSize, componentHeight); 

     // Set the label's font size to the newly determined size. 
     label.setFont(new Font(labelFont.getName(), Font.PLAIN, 
       (int) fontSizeToUse - 1)); 
    } 
} 
+0

減少一點代碼..更好地發佈完整的異常堆棧.. – Serhiy 2014-10-09 13:08:42

+0

經驗法則:如果你曾寫過「這裏是所有代碼」,那麼你可能做錯了。 – Voo 2014-10-09 13:38:38

+0

我做錯了...而且我沒有看到問題。 – 2014-10-09 15:06:34

回答

1

我沒有在你的代碼示例看,因爲有這麼多了,但有一個簡單的答案,你在你的標題提出的問題。

問:您如何使用線程將一個客戶端的輸入廣播到所有其他客戶端?

答:你沒有。

使用每個客戶端線程接收輸入從每個客戶端,並且在客戶端C發送你的東西,讓一個線程是服務客戶端C廣播消息到所有其他客戶端插座的。

相關問題