2011-11-03 41 views
0

這一定很容易,但我顯然缺少一些基本的理解。 我有簡單的客戶端服務器應用程序Java:client-sever app.- WHILE on ObjectInputStream讀取線程

服務器:

public class GameServer{ 
    private Socket clientSocket; 
    private ServerSocket serverSocket; 
    private ArrayList<ObjectOutputStream> oosPlayers=new ArrayList<ObjectOutputStream>(); 

    public static void main(String args[]){ 
     GameServer server = new GameServer(); 
     server.startGame(); 
    } 

    public void startGame(){ 
     try{ 
     serverSocket = new ServerSocket(10008); 
     System.out.println("Server started at:" + serverSocket); 
     while(true){ 
      System.out.println("Server: Waiting for client requests..."); 
      clientSocket=serverSocket.accept(); 
      System.out.println("Server: Client connection accepted at:"+clientSocket); 
      //remember player's output stream 
      oosPlayers.add(new ObjectOutputStream(clientSocket.getOutputStream())); 
      //read data from clients 
      Thread receiverThread = new Thread(new DataReceiver()); 
      receiverThread.start(); 
     } 
     } 
     catch(IOException ex){ 
      System.out.println(ex.getMessage()); 
     } 
    } 
    public class DataReceiver implements Runnable{ 
     public void run(){ 
      try{ 
       String mess; 
       ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream()); 
       while((mess=(String)ois.readObject()) != null){       
        System.out.println("Server: "+mess); 
        send(); 
       } 
      } 
      catch(Exception ex){ System.out.println(ex.getMessage()); } 
     } 
     public void send(){ 
      for (ObjectOutputStream oos : oosPlayers){ 
       try{ 
        oos.writeObject(new String("There is "+oosPlayers.size()+" player(s) at the board"));     
        oos.flush(); 
       } 
       catch(Exception ex){ System.out.println(ex.getMessage()); } 
      } 
     } 
    }   
} 

客戶端:

public class GameClient implements ActionListener{ 
    private Socket socket; 
    private ObjectInputStream ois; 
    private ObjectOutputStream oos; 
    private JButton button; 

    public static void main(String args[]){ 
     GameClient client = new GameClient(); 
     client.drawBoard(); 
    } 
    public void drawBoard(){ 
     JFrame frame = new JFrame("A game"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     button = new JButton("Send"); 
     button.addActionListener(this); 
     configureConnection(); 
     Thread receiverThread = new Thread(new DataReceiver()); 
     receiverThread.start(); 

     frame.getContentPane().add(new JPanel().add(button)); 
     frame.setSize(200,200); 
     frame.setVisible(true); 
    } 
    public void configureConnection(){ 
     try{ 
      socket = new Socket("127.0.0.1", 10008); 
      ois = new ObjectInputStream(socket.getInputStream()); 
      oos = new ObjectOutputStream(socket.getOutputStream()); 
     } 
     catch(Exception ex) { System.out.println(ex.getMessage()); } 
    } 

    public void actionPerformed(ActionEvent ev){ 
     if (ev.getSource()==button){ 
      try{ 
       oos.writeObject(new String("Some data from client")); 
       oos.flush(); 
      } 
      catch(Exception ex){ System.out.println(ex.getMessage()); }   
     } 
    } 

    public class DataReceiver implements Runnable{ 
     public void run(){ 
      try{ 
       String mess; 
       while((mess=(String)ois.readObject())!= null){     
        System.out.println("Client:"+mess); 
       } 
      } 
      catch(Exception ex){ System.out.println(ex.getMessage()); } 
     } 
    } 
} 

我的問題涉及到receiverThread兩側。當我在從ObjectInputStream(在RUN方法中)讀取時使用WHILE時,服務器偵聽客戶端請求,並將其正確地分派給所有ObjectOutputStream s。如果我將這個WHILE更改爲IF每個客戶端僅從服務器讀取(併發送)數據。這同樣適用於客戶的WHILE/IF。

我的理解是,當我運行receiverThread它以某種方式停止線程在WHILE並繼續讀輸入流,而使用IF讓線程完成(從而停止讀取過程)。儘管WHILE條件不滿足,即最初(沒有客戶端連接),但它如何保持receiverThread還活着。在receiverThread已經讀取數據並且流中沒有任何內容的情況下會發生同樣的情況。

希望對這個基本問題有一些解釋。

問候 馬辛

回答

0

如果改變而如果你run()方法,你看只有一個對象,並退出。如果你的客戶 - 服務器協議非常簡單,例如他們每個會話只發送一個對象,兩個版本都相同。否則,系統將無法正常工作:其他所有對象都不會到達。

+0

感謝您的回答。我仍然好奇,第一次'while((mess =(String)ois.readObject())!= null)'在服務器上執行時,條件失敗(流爲空),但它沒有退出運行方法並持續監聽輸入流。 –

+0

它不會繼續監聽InputStream。它正在監聽* socket *,因爲您尚未關閉它。清除實現應該用try/finally塊封裝while循環,並在finally塊中關閉流。 – AlexR

+0

這可能是不正確的,但我相信它不會退出'while((mess =(String)ois.readObject())!= null)',因爲你的套接字處於_blocking mode_中,並且讀線程會阻塞readObject()方法,直到它讀取數據或關閉套接字(這會導致引發Exception)。 –