2011-11-03 42 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)。 –