2015-04-07 107 views
2

我有這樣的服務器類,將消息發送給特定的客戶端線程

import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.ArrayList; 

public class Server { 
    public static ArrayList<String> waiting = new ArrayList<String>(); 
    public static ArrayList<String> playing = new ArrayList<String>(); 
    public static ArrayList<Integer> score = new ArrayList<Integer>(); 

    public static void main(String[] args) { 
     try { 
      ServerSocket server = new ServerSocket(4321); 
      while (true) { 
       try { 
        Socket socket = server.accept(); 
        new EchoThread(socket).start(); 
       } catch (Exception exc) { 
        exc.printStackTrace(); 
       } 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public void addClient(String name) { 
     waiting.add(name); 
    } 

    public int getNumClients() { 
     return waiting.size(); 
    } 

    public String getClientName(int i) { 
     return waiting.get(i); 
    } 

    public void play() { 
     int scr = 0; 
     for (int i = 0; i < 4; i++) { 
      playing.add(waiting.get(0)); 
      score.add(scr); 
      waiting.remove(0); 
     } 
    } 

    public boolean checkIfPlaying(String name) { 
     if (playing.indexOf(name) >= 0) { 
      return true; 
     } else { 
      return false; 
     } 
    } 
} 

和線程類,

import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.net.Socket; 

public class EchoThread extends Thread { 
    protected Socket socket; 

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

    public void run() { 
     Server s = new Server(); 
     DataInputStream in = null; 
     DataOutputStream out = null; 
     String line; 

     try { 
      in = new DataInputStream(socket.getInputStream()); 
      out = new DataOutputStream(socket.getOutputStream()); 
     } catch (IOException e) { 
      return; 
     } 

     while (true) { 
      try { 
       line = in.readLine(); 
       String[] prot = line.split(":"); 

       if (prot[0].equals("/login")) { 
        s.addClient(prot[1]); 
       } else if (prot[0].equals("/waiting")) { 
        if (s.checkIfPlaying(prot[1])) { 
         out.writeBytes("Playing" + "\r\n"); 
        } else { 
         if (s.getNumClients() >= 4) { 
          s.play(); 
          out.writeBytes("Playing" + "\r\n"); 
         } else { 
          out.writeBytes(s.getNumClients() + "\r\n"); 
         } 
        } 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
       return; 
      } 
     } 
    } 
} 

如果客戶端連接到服務器,客戶端的名稱存儲在服務器類數組中,等待。 如果等待的客戶端等於4,它將從等待陣列中移除並將其放入播放陣列中。

我想讓服務器發送消息給播放數組中的前4個客戶端。

我該怎麼辦?

+0

您是否正在存儲等待客戶端的IP /端口? –

+0

@Ziad,不,我需要存儲它嗎? –

回答

0

對於您的服務器類,我會更改您的ArrayList < String>用於等待並播放ArrayList < EchoThread>。這樣你的服務器類就可以跟蹤每個客戶對象本身,而不僅僅是他們的名字。當你實例化你的EchoThread對象時,我會將本地服務器對象傳遞給每個EchoThread,這樣每個對象都知道實例化它們的服務器。

服務器類

import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.ArrayList; 

public class Server { 
    public ArrayList<EchoThread> waiting = new ArrayList<EchoThread>(); 
    public ArrayList<EchoThread> playing = new ArrayList<EchoThread>(); 
    public ArrayList<Integer> score = new ArrayList<Integer>(); 

    public static void main(String[] args) { 
     try { 
      // Instantiate a single server object that you can pass into your connected clients 
      Server myServer = new Server(); 
      ServerSocket server = new ServerSocket(4321); 
      while (true) { 
       try { 
        Socket socket = server.accept(); 
        // Pass myServer into Echo Thread 
        new EchoThread(myServer, socket).start(); 
       } catch (Exception exc) { 
        exc.printStackTrace(); 
       } 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    // Have to synchronize this since multiple clients could be adding to this list at the same time 
    public synchronized void addClient(EchoThread client) { 
     waiting.add(client); 
    } 

    public int getNumClients() { 
     return waiting.size(); 
    } 

    public String getClientName(int i) { 
     return waiting.get(i).getCName(); 
    } 

    public void play() { 
     int scr = 0; 
     for (int i = 0; i < 4; i++) { 
      EchoThread clientBeingMovedToPlaying = waiting.get(0); 
      playing.add(clientBeingMovedToPlaying); 
      score.add(scr); 
      waiting.remove(0); 

      // This will be a new method in your EchoThread class 
      clientBeingMovedToPlaying.SendServerPlayingMessage(); 
     } 
    } 

    public boolean checkIfPlaying(String name) { 
     boolean isPlaying = false; 
     for(EchoThread client : playing) { 
      if (client.getName().contentEquals(name)) { 
       isPlaying = true; 
       break; 
      } 
     } 
     return isPlaying; 
    } 
} 

爲了您的迴音Thread類,我會做你的變量在您的run方法類變量,使他們能夠在整個類使用

EchoThread類

import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.net.Socket; 

public class EchoThread extends Thread { 
    protected Socket socket; 
    protected Server s; 
    protected DataInputStream in; 
    protected DataOutputStream out; 
    protected String line; 
    protected String clientName; 

    // This way, each EchoThread object knows about the server 
    public EchoThread(Server theServer, Socket clientSocket) { 
     this.s = theServer; 
     this.socket = clientSocket; 
    } 

    public void run() { 
     try { 
      in = new DataInputStream(socket.getInputStream()); 
      out = new DataOutputStream(socket.getOutputStream()); 
     } catch (IOException e) { 
      return; 
     } 

     while (true) { 
      try { 
       line = in.readLine(); 
       String[] prot = line.split(":"); 

       if (prot[0].equals("/login")) { 
        // Original code 
        //s.addClient(prot[1]); 

        // New code 
        clientName = prot[1]; 
        s.addClient(this); 
       } else if (prot[0].equals("/waiting")) { 
        if (s.checkIfPlaying(prot[1])) { 
         out.writeBytes("Playing" + "\r\n"); 
        } else { 
         // You don't want multiple clients firing the play method, so you need to synchronize your server object 
         synchronized (s) { 
          if (s.getNumClients() >= 4) { 
           s.play(); 
           out.writeBytes("Playing" + "\r\n"); 
          } else { 
           out.writeBytes(s.getNumClients() + "\r\n"); 
          } 
         } 
        } 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
       return; 
      } 
     } 
    } 

    public String getCName() { 
     return clientName; 
    } 

    public void SendServerPlayingMessage() { 
     if (out != null) { 
      // Send whatever message you want 
     } 
    } 
} 

我認爲這會得到你想要的東西......原諒任何語法或邏輯錯誤,我目前沒有一個IDE在我面前。

+0

有一個錯誤,發送EchoThread,我怎樣才能把它作爲參數發送? EchoThread本身? –

+0

在EchoThread類中,我做了一些編輯。我已經添加了一個客戶端名稱作爲字符串,所以你仍然可以保持客戶端的名稱作爲對象的一部分。然後當你調用s.addClient()時,只需傳遞這個關鍵字即可。 – Shar1er80

+0

非靜態變量不能從靜態上下文中引用 –

相關問題